Javascript 代碼: 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[n]; } this.set = function(n, v) { options[n] = 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[n] = b[n]; } 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; } } })()
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canvas</title> <script src="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>
這個類提供了一個簡單的信息框,幫助您監控代碼的性能。 html
項目主頁:http://www.open-open.com/lib/view/home/1414374727419 java
源碼:https://github.com/mrdoob/stats.js android