You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

102 lines
3.3 KiB

(function (global) {
'use strict';
/**
* Lightweight Canvas2D ring-buffer line chart with marker lines.
* @constructor
* @param {HTMLCanvasElement} canvas
*/
function RingChart(canvas) {
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
this.color = '#3794ff';
this.fill = 'rgba(55,148,255,0.15)';
this.min = null;
this.max = null;
}
/**
* Draw series and markers.
* @param {number[]} values
* @param {{t:number,label:string}[]} markers
* @param {number[]} times
*/
RingChart.prototype.draw = function (values, markers, times) {
var ctx = this.ctx;
var canvas = this.canvas;
var dpr = window.devicePixelRatio || 1;
var cssW = canvas.clientWidth || 220;
var cssH = canvas.clientHeight || 72;
if (canvas.width !== Math.floor(cssW * dpr) || canvas.height !== Math.floor(cssH * dpr)) {
canvas.width = Math.floor(cssW * dpr);
canvas.height = Math.floor(cssH * dpr);
}
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
ctx.clearRect(0, 0, cssW, cssH);
ctx.fillStyle = '#111';
ctx.fillRect(0, 0, cssW, cssH);
if (!values || values.length < 2) {
ctx.fillStyle = '#666';
ctx.fillText('暂无数据', 8, 20);
return;
}
var min = this.min;
var max = this.max;
if (min == null || max == null) {
min = values[0];
max = values[0];
for (var i = 1; i < values.length; i++) {
if (values[i] < min) min = values[i];
if (values[i] > max) max = values[i];
}
if (min === max) {
min -= 1;
max += 1;
}
}
var pad = 2;
var t0 = times && times.length ? times[0] : 0;
var t1 = times && times.length ? times[times.length - 1] : values.length - 1;
var span = Math.max(1, t1 - t0);
if (markers && markers.length && times && times.length) {
ctx.strokeStyle = 'rgba(241,76,76,0.7)';
ctx.lineWidth = 1;
for (var m = 0; m < markers.length; m++) {
var mt = markers[m].t;
if (mt < t0 || mt > t1) continue;
var mx = pad + ((mt - t0) / span) * (cssW - pad * 2);
ctx.beginPath();
ctx.moveTo(mx, 0);
ctx.lineTo(mx, cssH);
ctx.stroke();
}
}
ctx.beginPath();
for (var j = 0; j < values.length; j++) {
var x = pad + (j / (values.length - 1)) * (cssW - pad * 2);
var y = cssH - pad - ((values[j] - min) / (max - min)) * (cssH - pad * 2);
if (j === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
}
ctx.strokeStyle = this.color;
ctx.lineWidth = 1.5;
ctx.stroke();
ctx.lineTo(pad + (cssW - pad * 2), cssH - pad);
ctx.lineTo(pad, cssH - pad);
ctx.closePath();
ctx.fillStyle = this.fill;
ctx.fill();
ctx.fillStyle = '#aaa';
ctx.font = '10px Consolas, monospace';
var last = values[values.length - 1];
ctx.fillText(String(Math.round(last * 100) / 100), 4, 12);
};
global.PWRingChart = RingChart;
})(window);