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
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);
|
|
|