// 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 };