2 changed files with 238 additions and 45 deletions
@ -1,47 +1,232 @@ |
|||
import moment from "moment"; |
|||
import {h} from "vue"; |
|||
|
|||
export class BoxDrawer{ |
|||
|
|||
private canvas: any = null; |
|||
private canvasContext: any = null; |
|||
private borderWidth: number = 0; |
|||
private borderHeight: number = 0; |
|||
|
|||
private readonly weight: number = null; |
|||
private readonly width: number = null; |
|||
private readonly height: number = null; |
|||
private readonly paddingLeft: number = 10; |
|||
private readonly paddingRight: number = 10; |
|||
private readonly paddingTop: number = 5; |
|||
private readonly paddingBottom: number = 5; |
|||
private readonly scaleLine: number = 4; |
|||
|
|||
constructor(weight: number, height: number) { |
|||
this.weight = weight; |
|||
private readonly paddingLeft: number = 100; |
|||
private readonly paddingRight: number = 100; |
|||
private readonly paddingTop: number = 50; |
|||
private readonly paddingBottom: number = 50; |
|||
private readonly colorChart: ColorChart = null; |
|||
private readonly values: any = null; |
|||
private readonly verticalScaleSpecialCount: number = 6; |
|||
private readonly horizontalScaleSpecialCount: number = 6; |
|||
|
|||
// 垂直刻度
|
|||
private readonly verticalScaleLine: number = 18; |
|||
// 水平刻度
|
|||
private readonly horizontalScaleLine: number = 20; |
|||
public base64Image: string = null; |
|||
|
|||
private verticalScaleIntervalLength: number = 0; |
|||
private horizontalScaleIntervalLength: number = 0; |
|||
|
|||
constructor(width: number, height: number, colorChart: ColorChart, values: any) { |
|||
this.width = width; |
|||
this.height = height; |
|||
this.colorChart = colorChart; |
|||
this.values = values; |
|||
|
|||
this.init(); |
|||
// this.drawCoordinate();
|
|||
console.log(this.canvas.toDataURL()); |
|||
this.drawCoordinate(); |
|||
this.draw(); |
|||
this.base64Image = this.canvas.toDataURL(); |
|||
} |
|||
|
|||
private draw(): void{ |
|||
let startX = this.paddingLeft + this.horizontalScaleLine - this.verticalScaleIntervalLength / 2; |
|||
let startY = this.paddingTop + this.verticalScaleLine - this.horizontalScaleIntervalLength / 2; |
|||
for(let dataIndex = 0, len = this.values.radar_data.length, lastDataLen = len - 1; dataIndex < len; dataIndex++){ |
|||
// if (dataIndex > 0) return;
|
|||
for(let lastInfoLen = this.values.radar_info.length - 1, infoIndex = lastInfoLen; infoIndex >= 0; infoIndex--){ |
|||
let x = startX + dataIndex * this.verticalScaleIntervalLength; |
|||
let y = startY + (this.borderHeight - infoIndex * this.horizontalScaleIntervalLength); |
|||
let width = this.verticalScaleIntervalLength; |
|||
let height = this.horizontalScaleIntervalLength; |
|||
if (dataIndex == 0) { |
|||
x = x + this.verticalScaleIntervalLength / 2; |
|||
width = width / 2; |
|||
} |
|||
if (infoIndex == lastInfoLen){ |
|||
y = y + this.horizontalScaleIntervalLength / 2; |
|||
height = height / 2; |
|||
} |
|||
if (dataIndex == lastDataLen){ |
|||
width = width / 2; |
|||
} |
|||
if (infoIndex == 0){ |
|||
height = height / 2; |
|||
} |
|||
|
|||
let color = this.colorChart.getColor(this.values.radar_data[dataIndex][this.values.radar_info[infoIndex].col_name]); |
|||
if (color == null) continue; |
|||
this.canvasContext.fillStyle = color; |
|||
this.canvasContext.fillRect(x, y, width, height); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private resetValues() : void{ |
|||
this.values.radar_data.sort((a, b) => { |
|||
return moment(a.data_time).isBefore(b.data_time, 'second'); |
|||
}); |
|||
|
|||
this.values.radar_info.sort((a, b) => { |
|||
return a.col_factor - b.col_factor; |
|||
}); |
|||
} |
|||
|
|||
private init(): void{ |
|||
// 创建画布
|
|||
this.canvas = document.createElement('canvas'); |
|||
this.canvas.weight = this.weight; |
|||
this.canvas.width = this.width; |
|||
this.canvas.height = this.height; |
|||
|
|||
this.canvasContext = this.canvas.getContext('2d'); |
|||
|
|||
this.resetValues(); |
|||
} |
|||
|
|||
private drawCoordinate(): void{ |
|||
this.drawBorder(); |
|||
this.drawVerticalScale(); |
|||
this.drawHorizontalScale(); |
|||
} |
|||
|
|||
private drawVerticalScale(): void{ |
|||
let scaleCount = this.values.radar_data.length; |
|||
this.verticalScaleIntervalLength = this.borderWidth / (scaleCount - 1); |
|||
let scaleSpecial = parseInt((scaleCount * 1.0 / this.verticalScaleSpecialCount).toString()); |
|||
|
|||
let startX = this.paddingLeft + this.horizontalScaleLine; |
|||
let startY = this.paddingTop + this.verticalScaleLine; |
|||
for(let index = 0, len = scaleCount, lastLen = scaleCount - 1; index < len; index++){ |
|||
if (index == 0 || index == lastLen) continue; |
|||
|
|||
const flag = index % scaleSpecial == 0; |
|||
this.setScaleStyle(flag); |
|||
const yInterval = flag ? this.verticalScaleLine : this.verticalScaleLine / 2; |
|||
|
|||
const _x = startX + index * this.verticalScaleIntervalLength; |
|||
this.canvasContext.beginPath(); |
|||
this.canvasContext.moveTo(_x, startY); |
|||
this.canvasContext.lineTo(_x,startY - yInterval); |
|||
this.canvasContext.moveTo(_x, startY + this.borderHeight); |
|||
this.canvasContext.lineTo(_x,startY + yInterval + this.borderHeight); |
|||
this.canvasContext.stroke(); |
|||
|
|||
if (flag){ |
|||
this.canvasContext.font = "normal 36px Verdana"; |
|||
this.canvasContext.fillStyle = "#000000"; |
|||
const text = moment(this.values.radar_data[index].data_time).format("HH:mm"); |
|||
this.canvasContext.fillText(text, _x - this.canvasContext.measureText(text).width / 2, startY + yInterval + this.borderHeight + 36); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private drawHorizontalScale(): void{ |
|||
let scaleCount = this.values.radar_info.length; |
|||
this.horizontalScaleIntervalLength = this.borderHeight / (scaleCount - 1); |
|||
let scaleSpecial = parseInt((scaleCount * 1.0 / this.verticalScaleSpecialCount).toString()); |
|||
let startX = this.paddingLeft + this.horizontalScaleLine; |
|||
let startY = this.paddingTop + this.verticalScaleLine; |
|||
const lastLen = scaleCount - 1; |
|||
for(let index = lastLen; index >= 0; index--){ |
|||
const flag = index % scaleSpecial == 0; |
|||
this.setScaleStyle(flag); |
|||
const xInterval = flag? this.horizontalScaleLine : this.horizontalScaleLine / 2; |
|||
|
|||
const _y = startY + (this.borderHeight - index * this.horizontalScaleIntervalLength); |
|||
this.canvasContext.beginPath(); |
|||
this.canvasContext.moveTo(startX, _y); |
|||
this.canvasContext.lineTo(startX - xInterval, _y); |
|||
this.canvasContext.moveTo(this.borderWidth + startX, _y); |
|||
this.canvasContext.lineTo(this.borderWidth + startX + xInterval, _y); |
|||
this.canvasContext.stroke(); |
|||
|
|||
if (flag){ |
|||
this.canvasContext.font = "normal 36px Verdana"; |
|||
this.canvasContext.fillStyle = "#000000"; |
|||
const text = this.values.radar_info[index].col_factor; |
|||
this.canvasContext.fillText(text, startX - this.canvasContext.measureText(text).width - this.horizontalScaleLine, _y + 18); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private setScaleStyle(isSpecial: boolean): void{ |
|||
if (isSpecial){ |
|||
this.canvasContext.lineWidth = 5; |
|||
this.canvasContext.strokeStyle = '#F41006'; |
|||
return; |
|||
} |
|||
|
|||
this.canvasContext.lineWidth = 2; |
|||
this.canvasContext.strokeStyle = '#444'; |
|||
} |
|||
|
|||
private drawBorder(): void{ |
|||
const x = this.scaleLine + this.paddingLeft; |
|||
const y = this.scaleLine + this.paddingTop; |
|||
const _x = this.weight - this.scaleLine - this.paddingRight; |
|||
const _y = this.height - this.scaleLine - this.paddingBottom; |
|||
const x = this.horizontalScaleLine + this.paddingLeft; |
|||
const y = this.verticalScaleLine + this.paddingTop; |
|||
const _x = this.width - this.horizontalScaleLine - this.paddingRight; |
|||
const _y = this.height - this.verticalScaleLine - this.paddingBottom; |
|||
|
|||
this.canvasContext.beginPath(); |
|||
this.canvasContext.lineWidth="6"; |
|||
this.canvasContext.strokeStyle="red"; |
|||
this.canvasContext.rect(x, y, _x - x, _y - y); |
|||
this.canvasContext.lineWidth = "2"; |
|||
this.canvasContext.strokeStyle = "black"; |
|||
|
|||
this.borderWidth = _x - x; |
|||
this.borderHeight = _y - y; |
|||
this.canvasContext.rect(x, y, this.borderWidth, this.borderHeight); |
|||
this.canvasContext.stroke(); |
|||
} |
|||
} |
|||
|
|||
export class ColorChart{ |
|||
|
|||
private colors: any = null; |
|||
private values: any = null; |
|||
public showStartValue: boolean = false; |
|||
public showEndValue: boolean = false; |
|||
|
|||
private readonly valueLength: number = 0; |
|||
|
|||
constructor(colors: any, values: any, showStartValue: boolean = false, showEndValue: boolean = false) { |
|||
this.verify(colors, values); |
|||
this.colors = colors; |
|||
this.values = values; |
|||
this.showStartValue = showStartValue; |
|||
this.showEndValue = showEndValue; |
|||
this.valueLength = this.values.length; |
|||
|
|||
this.resetValues(); |
|||
} |
|||
|
|||
private resetValues(): void{ |
|||
if (this.values[0] < this.values[1]) return; |
|||
this.values = this.values.reverse(); |
|||
this.colors = this.colors.reverse(); |
|||
} |
|||
|
|||
private verify(colors: any, values: any): void{ |
|||
if (values.length <= 2) |
|||
throw new Error("色标数据至少包含两个数据"); |
|||
|
|||
if (colors.length != values.length - 1) |
|||
throw new Error("色标数据不正确,数据个数应为颜色个数 + 1"); |
|||
} |
|||
|
|||
public getColor(value: number): string{ |
|||
for(let index = 1; index < this.valueLength; index ++){ |
|||
if (this.values[index -1] <= value && this.values[index] > value){ |
|||
return this.colors[index - 1]; |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
} |
Loading…
Reference in new issue