您的位置:首页 > 其它

Canvas 可拖动的波形显示

2016-04-15 11:47 232 查看
Javascript 代码:

/*
* Canvas line
* Author:SongYi
* Date:2015-06-29
* Version:0.1
*/
(function() {
/* ****************************************************************************
* Handle the options                                                         *
*****************************************************************************/
var defaultOptions = {
colors: ['#00A600', '#D94600', '#921AFF', '#E800E8', '#C6A300', '#f7a35c',
'#8085e9', '#f15c80', '#e4d354', '#91e8e1'
],
datas: [],
global: {
width: 630,
height: 275,
border: true,
borderStyle: "1px solid #000"
},
chart: {
marginLeft: 80,
marginRight: 10,
marginTop: 5,
marginBottom: 30,
lineWidth: 1,
yStep: 40,
xStep: 60,
yRatio: 0,
xRatio: 0,
yMax: 10000,
yMin: 0,
xMax: 0,
xMin: 0,
yRealMax: 0,
yRealMin: 0
},
title: {
textY: '',
textX: '(s)',
style: {
color: '#000000',
font: '11pt Arial'
}
},
labels: {
marginLeft: 25,
marginTop: 5,
style: {
color: '#000000',
font: '9pt Arial'
}
}
};

function Canvasy(userOptions) {
var options = extend(defaultOptions, userOptions);
this.get = function(n) {
return options
;
}
this.set = function(n, v) {
options
= v;
}
this.init();
this.bindEvent();
}

Canvasy.prototype = {
/**
* Initialize the chart
*/
init: function() {
var ctx = this.get("ctx");
var global = this.get("global");
ctx.setAttribute('width', global.width);
ctx.setAttribute('height', global.height);
ctx = ctx.getContext("2d");
ctx.clearRect(0, 0, global.width, global.height);
this.initOption();
this.setTitleY();
this.drawAxis();
this.drawGridlinesX();
this.drawGridlinesY();
this.setAxisLabelX();
this.setAxisLabelY();
this.drawLines();
},
initOption: function() {
var global = this.get("global");
var chart = this.get("chart");
var lines = this.get("datas");
chart.baseY = global.height - chart.marginBottom;
chart.baseX = global.width - chart.marginRight;
chart.yStep = (global.height - chart.marginTop - chart.marginBottom) / 6;
chart.xStep = (global.width - chart.marginLeft - chart.marginRight) / 9;
chart.yRatio = (chart.baseY - chart.marginTop) / (chart.yMax - chart.yMin);
chart.xRatio = (chart.baseX - chart.marginLeft) / (chart.xMax - chart.xMin);
this.set("chart", chart);
},
setTitleY: function() {
var ctx = this.get("ctx").getContext("2d");
var chart = this.get("chart");
ctx.save();
ctx.rotate(-90 * Math.PI / 180);
ctx.font = this.get("title").style.font;
ctx.fillStyle = this.get("title").style.color;
ctx.textAlign = 'center';
ctx.fillText(this.get("title").textY, -80, 20);
ctx.restore();
},
drawAxis: function() {
// X axis
var ctx = this.get("ctx").getContext("2d");
var global = this.get("global");
var chart = this.get("chart");
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = "#000000";
ctx.moveTo(chart.marginLeft, global.height - chart.marginBottom);
ctx.lineTo(global.width - chart.marginRight, global.height - chart.marginBottom);
ctx.stroke();

ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = "#000000";
ctx.moveTo(chart.marginLeft, chart.marginTop);
ctx.lineTo(chart.marginLeft, global.height - chart.marginBottom);
ctx.stroke();
},
drawGridlinesX: function() {

var ctx = this.get("ctx").getContext("2d");
var height = this.get("global").height;
var lines = this.get("datas");
var chart = this.get("chart");
if (typeof lines !== 'undefined' && lines.length > 0) {
if (chart.xMax < 10 || isInteger(chart.xMax)) {
for (var i = 2; i <= 10; i++) {
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = "#D7D7D7";
ctx.moveTo((i - 1) * chart.xStep + chart.marginLeft, chart.marginTop);
ctx.lineTo((i - 1) * chart.xStep + chart.marginLeft, height - chart.marginBottom);
ctx.stroke();
}
} else {
var xAxisMax = Math.floor(chart.xMax);
for (var i = 0; i < 9; i++) {
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = "#D7D7D7";
ctx.moveTo(chart.baseX - ((chart.xMax - xAxisMax) + i) * chart.xStep, chart.marginTop);
ctx.lineTo(chart.baseX - ((chart.xMax - xAxisMax) + i) * chart.xStep, height - chart.marginBottom);
ctx.stroke();
}
}
}
},
drawGridlinesY: function() {
var ctx = this.get("ctx").getContext("2d");
var width = this.get("global").width;
var chart = this.get("chart");
for (var i = 0; i <= 5; i++) {
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = "#D7D7D7";
ctx.moveTo(chart.marginLeft, i * chart.yStep + 5);
ctx.lineTo(width - chart.marginRight, i * chart.yStep + 5);
ctx.stroke();
}

},
drawLines: function() {
var ctx = this.get("ctx").getContext("2d");
var lines = this.get("datas");
var colors = this.get("colors");
var chart = this.get("chart");
var global = this.get("global");
ctx.save();
ctx.rect(chart.marginLeft, chart.marginTop, global.width - chart.marginLeft - chart.marginRight, global.height - chart.marginBottom - chart.marginTop);
ctx.stroke();
ctx.clip();
ctx.lineCap = "round";
if (lines !== null && typeof lines !== 'undefined') {
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
ctx.beginPath();
ctx.strokeStyle = colors[i];
for (var j = 1; j < line.data.length; j++) {
var xPoint = line.data[j - 1];
var point = line.data[j];
if (line.focus) {
ctx.lineWidth = 4 * chart.lineWidth;
} else {
ctx.lineWidth = chart.lineWidth;
}

ctx.moveTo(chart.baseX - round((chart.xMax - xPoint.x) * chart.xRatio) + line.p.X, chart.baseY - round((xPoint.y - chart.yMin) * chart.yRatio) + line.p.Y);
ctx.lineTo(chart.baseX - round((chart.xMax - point.x) * chart.xRatio) + line.p.X, chart.baseY - round((point.y - chart.yMin) * chart.yRatio) + line.p.Y);

}
ctx.stroke();
}
}
ctx.restore();
},
setAxisLabelY: function() {
var ctx = this.get("ctx").getContext("2d");
var chart = this.get("chart");
var global = this.get("global");
var labels = this.get("labels");
ctx.font = labels.style.font;
ctx.fillStyle = labels.style.color;
for (var i = 0; i <= 6; i++) {
ctx.fillText(round(chart.yRealMin + round((chart.yRealMax - chart.yRealMin) * i / 6)), labels.marginLeft, chart.baseY - i * chart.yStep + labels.marginTop);
}
},
setAxisLabelX: function() {
var ctx = this.get("ctx").getContext("2d");
var lines = this.get("datas");
var chart = this.get("chart");
var labels = this.get("labels");
var height = this.get("global").height;
ctx.font = labels.style.font;
ctx.fillStyle = labels.style.color;
if (typeof lines !== 'undefined' && lines.length > 0) {
if (chart.xMax < 10) {
for (var i = 0; i < 10; i++) {
ctx.fillText(i, i * chart.xStep + chart.marginLeft, height - 18);
}
chart.xMax = 9;
} else {
var xAxisMax = Math.floor(chart.xMax);
for (var i = 0; i < 9; i++) {
ctx.fillText(Math.floor(xAxisMax - (xAxisMax / 10) * i), chart.baseX - ((chart.xMax - xAxisMax) + i) * chart.xStep - 10, height - 18);
}
}
}
ctx.font = this.get("title").style.font;
ctx.fillStyle = this.get("title").style.color;
ctx.fillText(this.get("title").textX, chart.baseX - 30, height - 5);
},
setOptions: function(options) {
for (var p in options) {
this.set(p, options[p]);
}

this.init();
},
setDatas: function(datas) {
var lines = this.get("datas");
for (var i = 0; i < lines.length; i++) {
lines[i].focus = datas[i].focus;
lines[i].data = datas[i].data;
}
this.set("datas", lines);
this.init();
},
addPoint: function(points) {
if (points == null || points == 'undefined') {
return;
}
var lines = this.get("datas");
for (var i = 0; i < lines.length; i++) {
if (isArray(points)) {
for (var j = 0; j < points.length; j++) {
if (points[j].name == lines[i].name) {
lines[i].data.push(points[j].data);
}
}
} else {
if (points.name == lines[i].name) {
lines[i].data.push(points.data);
}
}
}
this.set("datas", lines);

this.init();
},
resize: function(width, height, drawFlag) {
var ctx = this.get("ctx");
var global = this.get("global");
global.width = width;
global.height = height;
ctx.setAttribute('width', width);
ctx.setAttribute('height', height);
if (drawFlag) {
this.init();
} else {
ctx = ctx.getContext("2d");
ctx.clearRect(0, 0, width, height);
}
},
setLineOffset: function(_p) {
var lines = this.get("datas");
for (var i = 0; i < lines.length; i++) {
if (lines[i].focus) {
lines[i].p = _p;
}
}
this.set("datas", lines);
},
OnMouseDown: function(evt) {
var X = evt.layerX;
var Y = evt.layerY;
if (!this.lineOffset) {
this.lineOffset = {
isDown: true,
sx: X,
sx: Y
};
} else {
this.lineOffset.isDown = true;
this.lineOffset.sx = X;
this.lineOffset.sy = Y;
}

},
OnMouseMove: function(evt) {
if (this.lineOffset && this.lineOffset.isDown) {
var X = evt.layerX - this.lineOffset.sx;
var Y = evt.layerY - this.lineOffset.sy;
this.setLineOffset({
X: X,
Y: Y
});
}
},
OnMouseUp: function(evt) {
this.lineOffset.isDown = false;
this.lineOffset.sx = 0;
this.lineOffset.sy = 0;
},
OnTouchStart: function(evt) {
var touch = event.targetTouches[0];
if (!this.lineOffset) {
this.lineOffset = {
isDown: true,
sx: touch.pageX,
sx: touch.pageY
};
} else {
this.lineOffset.isDown = true;
this.lineOffset.sx = touch.pageX;
this.lineOffset.sy = touch.pageY;
}
},
OnTouchMove: function(evt) {
var touch = event.targetTouches[0];
if (this.lineOffset && this.lineOffset.isDown) {
var X = touch.pageX - this.lineOffset.sx;
var Y = touch.pageY - this.lineOffset.sy;
this.setLineOffset({
X: X,
Y: Y
});
}
},
OnTouchEnd: function(evt) {
this.lineOffset.isDown = false;
this.lineOffset.sx = 0;
this.lineOffset.sy = 0;
},
bindEvent: function() {
var ctx = this.get("ctx");
if (isMobile()) {
ctx.addEventListener("touchstart", this.OnTouchStart.bind(this), false);
ctx.addEventListener("touchmove", this.OnTouchMove.bind(this), false);
ctx.addEventListener("touchend", this.OnTouchEnd.bind(this), false);
} else {
ctx.addEventListener("mousedown", this.OnMouseDown.bind(this), false);
ctx.addEventListener("mousemove", this.OnMouseMove.bind(this), false);
ctx.addEventListener("mouseup", this.OnMouseUp.bind(this), false);
}

}
}
// The Highcharts namespace
window.Canvasy = window.Canvasy || Canvasy;

/**
* Extend an object with the members of another
* @param {Object} a The object to be extended
* @param {Object} b The object to add to the first one
*/
var extend = Canvasy.extend = function(a, b) {
var n;
if (!a) {
a = {};
}
for (n in b) {
a
= b
;
}
return a;
};
/**
* Check for string
* @param {Object} s
*/
function isString(s) {
return typeof s === 'string';
}
/**
* Check for object
* @param {Object} obj
*/
function isObject(obj) {
return obj && typeof obj === 'object';
}

function isInteger(obj) {
return Math.floor(obj) === obj
}
/**
* Check for array
* @param {Object} obj
*/
function isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
/**
* Check for number
* @param {Object} n
*/
function isNumber(n) {
return typeof n === 'number';
}

function round(n) {
return Math.round(n * 100) / 100;
}

/**
* Non-recursive method to find the lowest member of an array. Math.min raises a maximum
* call stack size exceeded error in Chrome when trying to apply more than 150.000 points.
* This method is slightly slower, but safe.
*/
function arrayMin(data) {
if (data == null || data.length == 0) {
return 0;
}
var i = data.length,
min = data[0];

while (i--) {
if (data[i] < min) {
min = data[i];
}
}
return min;
}

function arrayMax(data) {
if (data == null || data.length == 0) {
return 0;
}
var i = data.length,
max = data[0];

while (i--) {
if (data[i] > max) {
max = data[i];
}
}
return max;
}
/**
* Provide error messages for debugging, with links to online explanation
*/
function error(code, stop) {
var msg = 'Canvasy error #' + code + ': ' + code;
if (stop) {
throw msg;
}
// else ...
if (window.console) {
console.log(msg);
}
}

function isMobile() {
var sUserAgent = navigator.userAgent.toLowerCase();

var bIsIpad = sUserAgent.match(/ipad/i) == "ipad";

var bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os";

var bIsMidp = sUserAgent.match(/midp/i) == "midp";

var bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4";

var bIsUc = sUserAgent.match(/ucweb/i) == "ucweb";

var bIsAndroid = sUserAgent.match(/android/i) == "android";

var bIsCE = sUserAgent.match(/windows ce/i) == "windows ce";

var bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile";

if (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM) {

return true;

} else {

return false;

}
}

})()


Html 代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>canvas</title>
<script src=
3ff0
"js/canvasy1.js" charset="utf-8"></script>
<script type="text/javascript" src="js/stats.min.js"></script>
<style media="screen">
body{
margin: 0 0;
width: 100%;
}
input[type="checkbox"]{
visibility: hidden;
}
.checkbox {
display: inline-table;
width: 40px;
height: 40px;
background: #ddd;
margin: 10px 20px;

border-radius: 100%;
position: relative;
-webkit-box-shadow: 0px 1px 3px rgba(0,0,0,0.5);
-moz-box-shadow: 0px 1px 3px rgba(0,0,0,0.5);
box-shadow: 0px 1px 3px rgba(0,0,0,0.5);
}
.checkbox label {
display: block;
width: 30px;
height: 30px;
border-radius: 100px;
line-height: 30px;
vertical-align: middle;
color: #fff;

-webkit-transition: all .5s ease;
-moz-transition: all .5s ease;
-o-transition: all .5s ease;
-ms-transition: all .5s ease;
transition: all .5s ease;
cursor: pointer;
position: absolute;
top: 5px;
left: 5px;
z-index: 1;

background: #333;

-webkit-box-shadow:inset 0px 1px 3px rgba(0,0,0,0.5);
-moz-box-shadow:inset 0px 1px 3px rgba(0,0,0,0.5);
box-shadow:inset 0px 1px 3px rgba(0,0,0,0.5);
}

.checkbox input[type=checkbox]:checked + label {
background: #26ca28;
}
</style>
</head>
<body>
<canvas id="canvas" width="800" height="400"></canvas>
<div class="checkbox" onclick="checkHandle(this);">
<input type="checkbox" name="name" value="0" checked="checked">
<label for="">CH1</label>
</div>
<div class="checkbox" onclick="checkHandle(this);">
<input type="checkbox" name="name" value="1" >
<label for="">CH2</label>
</div>
<div class="checkbox" onclick="checkHandle(this);">
<input type="checkbox" name="name" value="2" >
<label for="">CH3</label>
</div>
<div class="checkbox" onclick="checkHandle(this);">
<input type="checkbox" name="name" value="3" >
<label for="">CH4</label>
</div>
<div class="checkbox" onclick="checkHandle(this);">
<input type="checkbox" name="name" value="4" >
<label for="">CH5</label>
</div>
<div class="checkbox" onclick="checkHandle(this);">
<input type="checkbox" name="name" value="5" >
<label for="">CH6</label>
</div>
<div class="checkbox" onclick="checkHandle(this);">
<input type="checkbox" name="name" value="6" >
<label for="">CH7</label>
</div>
<div class="checkbox" onclick="checkHandle(this);">
<input type="checkbox" name="name" value="7" >
<label for="">CH8</label>
</div>
<script type="text/javascript">
var selected = 0;
function checkHandle(obj) {
var items = document.getElementsByTagName("input");
for(var i=0;items && items.length >0 && i < items.length;i++){
items[i].checked = false;
}
var chb=obj.children[0];
chb.checked = "checked";
selected = chb.value;
}
var stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.right = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);

function getDatas() {
var data = [];
for (i = 1; i <= 400; i++) {
data.push({
x: i/10,
y: Math.random()
});
}
return data;
}

var waveOptions = {
ctx: document.getElementById("canvas"),
global: {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight-100,
border: true,
borderStyle: "1px solid #000"
},
chart: {
marginLeft: 80,
marginRight: 10,
marginTop: 5,
marginBottom: 30,
lineWidth: 1,
yStep: 40,
xStep: 60,
yRatio: 0,
xRatio: 0,
yMax: 3,
yMin: -3,
xMax: 40,
xMin: 0,
yRealMax: 3,
yRealMin: -3
},
title: {
textY: 'wave',
textX: '(s)',
style: {
color: '#000000',
font: '12pt Arial'
}
},
datas: [{
p:{X:0,Y:0},
focus:true,
data: getDatas()
}, {
p:{X:0,Y:0},
focus:false,
data: getDatas()
}, {
p:{X:0,Y:0},
focus:false,
data: getDatas()
}, {
p:{X:0,Y:0},
focus:false,
data: getDatas()
}, {
p:{X:0,Y:0},
focus:false,
data: getDatas()
}, {
p:{X:0,Y:0},
focus:false,
data: getDatas()
}, {
p:{X:0,Y:0},
focus:false,
data: getDatas()
}, {
p:{X:0,Y:0},
focus:false,
data: getDatas()
}]
};
waveChart = new Canvasy(waveOptions);

setInterval(function(){
stats.begin();
var datas = [];
for (var i = 0; i < waveOptions.datas.length; i++) {
if(i == selected){
datas.push({
p:{X:0,Y:0},
focus:true,
data: getDatas()
});
}else{
datas.push({
p:{X:0,Y:0},
focus:false,
data: getDatas()
});
}
}
waveChart.setDatas(datas);
stats.end();
},40);

</script>
</body>
</html>


stats.js是一个JavaScript性能监控器。
这个类提供了一个简单的信息框,帮助您监控代码的性能。

FPS帧渲染的最后一秒。数字越高越好。

MS 渲染一帧需要毫秒。数字越低就越好。

项目主页:http://www.open-open.com/lib/view/home/1414374727419

源码:https://github.com/mrdoob/stats.js
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: