//
|
var util = require('../../utils/util.js');
|
|
class SignalChart {
|
|
constructor(objName, chartWidth, chartHeight, padding) {
|
this.objName = objName;
|
this.chartWidth = chartWidth;
|
this.chartHeight = chartHeight;
|
this.padding_top = 70; //this.getEleHeight(70);
|
this.padding_bottom = 35; //this.getEleHeight(50);
|
this.padding_left = 28; //this.getEleWidth(70);
|
this.padding_right = 5; //this.getEleWidth(20);
|
|
if (padding != null) {
|
if (padding.top != null) {
|
this.padding_top = padding.top;
|
}
|
}
|
this.ctx = wx.createCanvasContext(objName);
|
this.ctx.clearRect(0, 0, chartWidth, chartHeight) //清理一下
|
}
|
//坐标
|
initialChartCoord(coord) {
|
this.coord = coord;
|
}
|
initialChartTitle(chartTitle, padding_top, padding_left) {
|
this.chartTile = {
|
text: chartTitle,
|
padding_top: padding_top,
|
padding_left: padding_left
|
};
|
}
|
|
drawRefreshTimeText(text) {
|
const ctx = this.ctx;
|
ctx.setFillStyle('white')
|
ctx.fillRect(this.chartWidth - 80, 0, 80, 22)
|
//ctx.save();
|
//ctx.draw(true);
|
|
ctx.setFontSize(9);
|
ctx.setFillStyle('red');
|
|
ctx.fillText(text, this.getEleWidth(950), this.getEleHeight(18));
|
ctx.save();
|
ctx.draw(true);
|
}
|
addNewRecord(newRecord) {
|
this.records.push(newRecord);
|
this.draw(this.records);
|
}
|
addNewRecords(newRecords) {
|
this.records.push(newRecords);
|
this.draw(this.records);
|
}
|
clearAll() {
|
this.ctx.clearRect(0, 0, this.chartWidth, this.chartHeight) //清理一下
|
}
|
|
draw(records) {
|
this.records = records;
|
if (this.records == null || this.records.length<3)
|
return;
|
var that = this;
|
var coord = this.coord;
|
if (coord == null) {
|
coord = this.calcCoordValue(records);
|
}
|
|
var chartWidth = this.chartWidth;
|
var chartHeight = this.chartHeight;
|
//console.log("chartWidth:" + chartWidth);
|
//console.log("chartHeight:" + chartHeight);
|
const ctx = this.ctx;
|
|
|
var padding_top = this.padding_top;
|
var padding_bottom = this.padding_bottom;
|
var padding_left = this.padding_left;
|
var padding_right = this.padding_right;
|
var diagram_width = chartWidth - padding_left - padding_right;
|
var diagram_heigh = chartHeight - padding_top - padding_bottom;
|
|
//ctx.clearRect(padding_left, padding_top, diagram_width, diagram_heigh)//清理一下
|
|
|
|
const diagram_leftTop = {
|
x: padding_left,
|
y: padding_top
|
}
|
const diagram_leftBottom = {
|
x: padding_left,
|
y: padding_top + diagram_heigh
|
}
|
const diagram_rightTop = {
|
x: padding_left + diagram_width,
|
y: padding_top
|
}
|
|
//绘制区域
|
const grd = ctx.createLinearGradient(0, 0, 200, 0)
|
grd.addColorStop(0, '#7B68EE');
|
grd.addColorStop(1, '#87CEFF');
|
ctx.setFillStyle(grd);
|
ctx.fillRect(padding_left, padding_top, diagram_width, diagram_heigh);
|
ctx.stroke();
|
|
//标题
|
ctx.setFontSize(14);
|
ctx.setFillStyle('blue');
|
ctx.setTextAlign('center')
|
ctx.fillText(this.chartTile.text, this.chartTile.padding_left, this.chartTile.padding_top);
|
ctx.save();
|
|
ctx.beginPath();
|
|
|
|
|
//时间坐标
|
var coordTime = this.calcCoordTime(records[0], records[records.length - 1]);
|
|
//绘制曲线
|
for (var i = 0; i < records.length; i++) {
|
var pt = records[i];
|
var x = padding_left + (diagram_width * (pt.RecordValue - coord.Min) / (coord.Max - coord.Min));
|
var time = pt.RecordTime.replace(/-/g, '/');
|
|
var y = (new Date(time) - coordTime.Start) * diagram_heigh / coordTime.Total + padding_top;
|
if (i == 0) {
|
ctx.moveTo(x, y)
|
} else {
|
ctx.lineTo(x, y)
|
}
|
}
|
ctx.setLineWidth(2);
|
ctx.setStrokeStyle('red');
|
ctx.stroke();
|
//ctx.save()
|
|
//时间轴(刻度文字)
|
ctx.setTextAlign('center')
|
var step = 1;
|
if (coordTime.GridNumber>12)
|
step = 2;
|
for (var i = 0; i <= coordTime.GridNumber; i = i + step) {
|
var y = padding_top + i * diagram_heigh / coordTime.GridNumber;
|
var x = padding_left;
|
var t = new Date(coordTime.Start.getTime() + coordTime.Space * i);
|
|
var hour = t.getHours()
|
var minute = t.getMinutes();
|
if (minute<3){
|
ctx.moveTo(x, y);
|
ctx.lineTo(x - 5, y);
|
ctx.translate(x, y)
|
ctx.rotate(Math.PI / 2)
|
ctx.setFontSize(9)
|
ctx.fillText(hour, 0, 17)
|
ctx.rotate(-Math.PI / 2)
|
ctx.translate(-x, -y);
|
}
|
else{
|
minute = minute < 10 ? ('0' + minute) : minute;
|
ctx.moveTo(x, y);
|
ctx.lineTo(x - 5, y);
|
ctx.translate(x, y)
|
ctx.rotate(Math.PI / 2)
|
ctx.setFontSize(9)
|
ctx.fillText(hour + ":" + minute, 0, 17)
|
ctx.rotate(-Math.PI / 2)
|
ctx.translate(-x, -y);
|
}
|
|
}
|
|
//监控值坐标(刻度文字)
|
ctx.setTextAlign('right')
|
//ctx.setTextBaseline('middle')
|
for (var v = coord.Min; v <= coord.Max + 0.001; v = v + coord.Space) {
|
var y = padding_top;
|
var x = padding_left + (diagram_width * (v - coord.Min) / (coord.Max - coord.Min));
|
var str_v = util.valueFormat(v)
|
//console.log(str_v)
|
ctx.moveTo(x, y);
|
ctx.lineTo(x, y - 4);
|
ctx.translate(x, y)
|
ctx.rotate(Math.PI / 2)
|
ctx.setFontSize(9)
|
ctx.fillText(str_v, -10, 5)
|
ctx.rotate(-Math.PI / 2)
|
ctx.translate(-x, -y)
|
}
|
ctx.translate(0, 0)
|
ctx.setLineWidth(1);
|
ctx.setStrokeStyle('#707070');
|
ctx.stroke();
|
//ctx.save()
|
|
//GridLine 网格线
|
const space_dashLine = this.getEleWidth(15);
|
for (var v = coord.Min + coord.Space; v < coord.Max; v = v + coord.Space) {
|
var y = padding_top;
|
var x = padding_left + (diagram_width * (v - coord.Min) / (coord.Max - coord.Min));
|
this.drawDashLine(ctx, x, padding_top, x, padding_top + diagram_heigh, space_dashLine)
|
}
|
for (var i = 2; i < coordTime.GridNumber; i = i + 2) {
|
var y = padding_top + i * diagram_heigh / coordTime.GridNumber;
|
this.drawDashLine(ctx, padding_left, y, padding_left + diagram_width, y, space_dashLine)
|
}
|
|
//y轴
|
ctx.beginPath();
|
ctx.moveTo(diagram_leftTop.x, diagram_leftTop.y);
|
ctx.lineTo(diagram_rightTop.x, diagram_rightTop.y);
|
|
//x轴
|
ctx.moveTo(diagram_leftTop.x, diagram_leftTop.y);
|
ctx.lineTo(diagram_leftBottom.x, diagram_leftBottom.y);
|
ctx.setLineWidth(1);
|
ctx.setStrokeStyle('#707070')
|
ctx.stroke();
|
|
|
ctx.save();
|
|
|
ctx.draw(true)
|
}
|
//画虚线
|
drawDashLine(ctx, x1, y1, x2, y2, dashLength) { //传context对象,始点x和y坐标,终点x和y坐标,虚线长度
|
ctx.beginPath()
|
ctx.setLineWidth(0.5)
|
var dashLen = dashLength === undefined ? 3 : dashLength,
|
xpos = x2 - x1, //得到横向的宽度;
|
ypos = y2 - y1, //得到纵向的高度;
|
numDashes = Math.floor(Math.sqrt(xpos * xpos + ypos * ypos) / dashLen);
|
//利用正切获取斜边的长度除以虚线长度,得到要分为多少段;
|
for (var i = 0; i < numDashes; i++) {
|
if (i % 2 === 0) {
|
ctx.moveTo(x1 + (xpos / numDashes) * i, y1 + (ypos / numDashes) * i);
|
//有了横向宽度和多少段,得出每一段是多长,起点 + 每段长度 * i = 要绘制的起点;
|
} else {
|
ctx.lineTo(x1 + (xpos / numDashes) * i, y1 + (ypos / numDashes) * i);
|
}
|
}
|
ctx.stroke();
|
}
|
//为了获取宽度 //以宽度1000px设计稿做宽度的自适应
|
getEleWidth(w) {
|
var real = 0;
|
try {
|
var res = this.chartWidth;
|
var scale = 1000 / w;
|
real = Math.floor(res / scale);
|
return real;
|
} catch (e) {
|
return false;
|
}
|
}
|
//以宽度1000px设计稿做宽度的自适应
|
getEleHeight(w) {
|
var real = 0;
|
try {
|
var res = this.chartHeight;
|
var scale = 1000 / w;
|
real = Math.floor(res / scale);
|
return real;
|
} catch (e) {
|
return false;
|
}
|
}
|
formatNumber(n) {
|
n = n.toString()
|
return n[1] ? n : '0' + n
|
}
|
formatTimeByHour(date, hour, minute) {
|
var year = date.getFullYear();
|
var month = date.getMonth() + 1;
|
var day = date.getDate();
|
|
var second = 0;
|
if (hour >= 24) {
|
var nextDay = util.GetNextDate(date, 1);
|
var year = nextDay.getFullYear();
|
var month = nextDay.getMonth() + 1;
|
var day = nextDay.getDate();
|
hour = 0;
|
minute = 0;
|
second = 0;
|
var st = [year, month, day].map(this.formatNumber).join('-') + ' ' + [hour, minute, second].map(this.formatNumber).join(':');
|
return new Date(st.replace(/-/g, '/'));
|
} else {
|
var st = [year, month, day].map(this.formatNumber).join('-') + ' ' + [hour, minute, second].map(this.formatNumber).join(':');
|
return new Date(st.replace(/-/g, '/'));
|
}
|
}
|
calcCoordTime(startRecord, lastRecord) {
|
var startRecordTime = new Date(startRecord.RecordTime.replace(/-/g, '/'));
|
var endRecordTime = new Date(lastRecord.RecordTime.replace(/-/g, '/'));
|
var startRecordTime_new = this.formatTimeByHour(startRecordTime, startRecordTime.getHours(), 0);
|
var endRecordTime_new = this.formatTimeByHour(endRecordTime, endRecordTime.getHours() + 1, 0);
|
|
var coordTime = {};
|
coordTime.Start = startRecordTime_new;
|
coordTime.End = endRecordTime_new;
|
var totalTime = (endRecordTime_new - startRecordTime_new);
|
coordTime.Total = totalTime;
|
|
var startRecordTime_hour = startRecordTime_new.getHours();
|
var endRecordTime_hour = endRecordTime_new.getHours();
|
if (endRecordTime_hour == 0){
|
coordTime.GridNumber = 24 - startRecordTime_hour;
|
coordTime.Space = totalTime / coordTime.GridNumber;
|
return coordTime;
|
}
|
else{
|
coordTime.GridNumber = (endRecordTime_hour - startRecordTime_hour);
|
if (coordTime.GridNumber <= 0)
|
coordTime.GridNumber = 24;
|
coordTime.Space = totalTime / coordTime.GridNumber;
|
return coordTime;
|
}
|
|
}
|
//值坐标
|
optCoordValue(maxRecord) { //不能大于1
|
var coord = {};
|
if (maxRecord < 0.2) {
|
coord.Max = 0.2;
|
coord.Space = 0.05;
|
} else if (maxRecord < 0.3) {
|
coord.Max = 0.3;
|
coord.Space = 0.1;
|
} else if (maxRecord < 0.6) {
|
coord.Max = 0.6;
|
coord.Space = 0.2;
|
} else if (maxRecord < 0.8) {
|
coord.Max = 0.8;
|
coord.Space = 0.2;
|
} else {
|
coord.Max = 1;
|
coord.Space = 0.2;
|
}
|
return coord;
|
}
|
|
calcCoordValue(records) {
|
var coord = {};
|
//Max < coord.Min + 0.01 || coord.Space
|
var maxRecord = 0;
|
var nn = records.length;
|
for (var i = 0; i < nn; i++) {
|
var dataValue = records[i].RecordValue;
|
maxRecord = Math.max(maxRecord, dataValue);
|
}
|
if (maxRecord < 0.1) {
|
coord = this.optCoordValue(maxRecord * 10);
|
coord.Min = 0;
|
coord.Max = coord.Max / 10.0;
|
coord.Space = coord.Space / 10.0;
|
} else if (maxRecord < 1) {
|
coord = this.optCoordValue(maxRecord);
|
coord.Min = 0;
|
coord.Max = coord.Max;
|
coord.Space = coord.Space;
|
} else if (maxRecord < 10) {
|
coord = this.optCoordValue(maxRecord / 10.0);
|
coord.Min = 0;
|
coord.Max = coord.Max * 10;
|
coord.Space = coord.Space * 10;
|
} else if (maxRecord < 100) {
|
coord = this.optCoordValue(maxRecord / 100.0);
|
coord.Min = 0;
|
coord.Max = coord.Max * 100;
|
coord.Space = coord.Space * 100;
|
} else if (maxRecord < 1000) {
|
coord = this.optCoordValue(maxRecord / 1000.0);
|
coord.Min = 0;
|
coord.Max = coord.Max * 1000;
|
coord.Space = coord.Space * 1000;
|
} else if (maxRecord < 10000) {
|
coord = this.optCoordValue(maxRecord / 10000.0);
|
coord.Min = 0;
|
coord.Max = coord.Max * 10000;
|
coord.Space = coord.Space * 10000;
|
} else if (maxRecord < 100000) {
|
coord = this.optCoordValue(maxRecord / 100000.0);
|
coord.Min = 0;
|
coord.Max = coord.Max * 100000;
|
coord.Space = coord.Space * 100000;
|
} else {
|
coord.Min = 0;
|
coord.Max = util.valueFormat(maxRecord * 1.2);
|
coord.Space = coord.Max / 4;
|
}
|
|
return coord;
|
}
|
|
}
|
|
export {
|
SignalChart
|
};
|