/** * Description 构造函数 * Input : stringTypeNum, getRectWidth * Output : getCanvasContext, Text, Rect, Line, Arrow, Icon * other : 无 * author : lsb */ import { stringTypeNum, getRectWidth } from './canvasFunction'; let CONTEXT: any; // canvas的上下文 /** * 获取到canvas的context * @param {*} context canvas的上下文 * @return void */ function getCanvasContext(context: object): void { CONTEXT = context; } /** * 定义画文本的构造函数 * @param {string} textContent:文本内容 * @param {number} textX:文本的横坐标位置 * @param {number} textY:文本的纵坐标位置 * @param {string} textAlign:文本的对齐方式---'start':默认。文本在指定的位置开始 || 'end':结束 || 'center':文本的中心被放置在指定的位 置 ||'left':文本左对齐 || right:文本右对齐 *@param {string} textColor:文本的颜色 *@param {string} fontSize:字体大小 * @return {object} textCoordinate:文本的坐标 */ class Text { // tslint:disable-next-line:max-line-length constructor(public textContent: string, public textX: number, public textY: number, public textColor: string = 'gray', public textAlign: string = 'start', public fontSize: string = '12') { this.textContent = textContent; this.textX = textX; this.textY = textY; this.textColor = textColor; this.textAlign = textAlign; this.fontSize = fontSize + 'px'; } drawText(): object { // 画文本的方法 CONTEXT.beginPath(); CONTEXT.font = this.fontSize + ' ' + 'Arial'; CONTEXT.fillStyle = this.textColor; CONTEXT.textAlign = this.textAlign; CONTEXT.fillText(this.textContent, this.textX, this.textY); CONTEXT.closePath(); let stringSplit = this.fontSize.split('px'); let size = Number(stringSplit[0]); let textObj: any = stringTypeNum(this.textContent); let textCoordinate = { minX: this.textX, maxX: this.textX + textObj['numberAndEngNum'] * (size / 2 + 1) + textObj['chineseNum'] * size + textObj['otherNum'] * size / 2, minY: this.textY - size, maxY: this.textY }; return textCoordinate; } } /** * 定义画矩形的构造函数 * @param {number} rectX:矩形的横坐标位置 * @param {number} rectY:矩形的纵坐标位置 * @param {number} width:矩形的高 * @param {number} width:矩形的宽 * @param {string} textContent:矩形内文本的内容 * @param {string} textColor:矩形内文本的颜色 * @return void */ class Rect { // tslint:disable-next-line:max-line-length constructor(public rectX: number, public rectY: number, public width: number, public height: number, public textContent: string, public textColor: string = 'gray') { this.rectX = rectX; this.rectY = rectY; this.width = width; this.height = height; this.textContent = textContent; this.textColor = textColor; } drawRect(): void { // 画矩形的方法 let that = this; CONTEXT.beginPath(); CONTEXT.fillStyle = 'white'; CONTEXT.fillRect(this.rectX, this.rectY, this.width, this.height); CONTEXT.strokeStyle = '#D3D3D3'; CONTEXT.lineWidth = 1; CONTEXT.rect(this.rectX, this.rectY, this.width, this.height); CONTEXT.stroke(); let x = this.width / 2; let text = new Text(that.textContent, that.rectX + x, that.rectY + 14, that.textColor, 'center'); text.drawText(); CONTEXT.closePath(); } } /** * 定义画线条的构造函数 * @param {number} startX:开始画线条的横坐标位置 * @param {number} startY:开始画线条的纵坐标位置 * @param {number} endX:结束画线条的横坐标位置 * @param {number} endY:结束画线条的纵坐标位置 * @param {string} lineColor:线条的颜色 * @param {number} lineWidth:线条的宽度 * @param {string} lineCap:线条末端线帽的样式---'butt':默认。向线条的每个末端添加平直的边缘 || 'round':向线条的每个末端添加圆形线帽 || 'square':向线条的每个末端添加正方形线帽 * @return {object} lineEndCoordinate:线条末端的坐标 */ class Line { // tslint:disable-next-line:max-line-length constructor(public startX: number, public startY: number, public endX: number, public endY: number, public lineColor: string = '#D3D3D3', public lineWidth: number = 1.5, public lineCap: string = 'butt') { this.startX = startX; this.startY = startY; this.endX = endX; this.endY = endY; this.lineColor = lineColor; this.lineWidth = lineWidth; this.lineCap = lineCap; } drawLine(): object { // 画线的方法 CONTEXT.beginPath(); CONTEXT.lineWidth = this.lineWidth; CONTEXT.lineCap = this.lineCap; CONTEXT.strokeStyle = this.lineColor; let roundStartX = Math.round(this.startX) + 0.5; let roundStartY = Math.round(this.startY) - 0.5; let roundEndX = Math.round(this.endX) + 0.5; let roundEndY = Math.round(this.endY) - 0.5; // 减0.5的原因是因为canvas画线的宽是以中间往两边话的,注意这里是个坑 // 详细原因请看链接:https://segmentfault.com/q/1010000010381236 CONTEXT.moveTo(roundStartX, roundStartY); CONTEXT.lineTo(roundEndX, roundEndY); CONTEXT.stroke(); CONTEXT.closePath(); let lineEndCoordinate = { lineEndCoordinateX: roundEndX, lineEndCoordinateY: roundEndY, }; return lineEndCoordinate; } } /** * 定义画箭头的构造函数 * @param {number} startX:开始画箭头的横坐标位置 * @param {number} startY:开始画箭头的纵坐标位置 * @param {number} endX:结束画箭头的横坐标位置 * @param {number} endY:结束画箭头的纵坐标位置 * @param {string} lineColor:箭头的颜色 * @param {number} lineWidth:箭头线条的宽度 * @param {string} lineCap:线条末端线帽的样式---'butt':默认。向线条的每个末端添加平直的边缘 || 'round':向线条的每个末端添加圆形线帽 || 'square':向线条的每个末端添加正方形线帽 * @return {object} arrowEndCoordinate:箭头末端的坐标 */ class Arrow { // tslint:disable-next-line:max-line-length constructor(public startX: number, public startY: number, public endX: number, public endY: number, public lineColor: string = 'gray', public lineWidth: number = 1.5, public lineCap: string = 'butt') { this.startX = startX; this.startY = startY; this.endX = endX; this.endY = endY; this.lineColor = lineColor; this.lineWidth = lineWidth; this.lineCap = lineCap; } drawArrow(): object { // 画箭头的方法 let that = this; let line = new Line(that.startX, that.startY, that.endX, that.endY, 'black', that.lineWidth); line.drawLine(); CONTEXT.beginPath(); CONTEXT.lineWidth = this.lineWidth; CONTEXT.lineCap = this.lineCap; CONTEXT.strokeStyle = 'black'; CONTEXT.fillStyle = 'black'; CONTEXT.moveTo(this.startX, this.startY); let gradient = 3; // 三角形的斜率 let angle = 45; // 三角形的角度 let arrowP1X = Math.round(this.startX + gradient / Math.cos(angle * (Math.PI / 180))); // arrowP1点的横坐标 let arrowP1Y = Math.round(this.startY - gradient / Math.sin(angle * (Math.PI / 180))); // arrowP1点的纵坐标 CONTEXT.lineTo(arrowP1X, arrowP1Y); let arrowP2X = arrowP1X; // arrowP2点的横坐标 let arrowP2Y = Math.round(this.startY + gradient / Math.sin(angle * (Math.PI / 180))); // arrowP2点的纵坐标 CONTEXT.lineTo(arrowP2X, arrowP2Y); CONTEXT.lineTo(this.startX, this.startY); CONTEXT.fill(); CONTEXT.stroke(); CONTEXT.closePath(); let arrowEndCoordinate = { arrowEndCoordinateX: this.endX, arrowEndCoordinateY: this.endY, }; return arrowEndCoordinate; } } /** * 定义画图标的构造函数 * @param {object} iconType:图标的类型---natImgUrl || slbImgUrl || switchImgUrl || routeImgUrl * @param {number} iconX:图标的横坐标位置 * @param {number} iconY:图标的纵坐标位置 * @param {string} rectContent:图标右下角矩形的内容 * @return {object} iconInfo:图标的左右长的中心的坐标和图标的信息---leftCoordinate:左中心坐标 && rightCoordinate:右中心坐标 && icon:图标的信息 */ class Icon { constructor(public iconType: any, public iconX: number, public iconY: number, public rectContent: string) { this.iconType = iconType; this.iconX = iconX; this.iconY = iconY; this.rectContent = rectContent; } drawIcon(): object { // 画图标的方法 let that = this; let img = new Image(); img.src = this.iconType['imgUrl']; let iconInfo: any = {}; img.onload = () => { CONTEXT.drawImage(img, that.iconX, that.iconY, that.iconType['width'], that.iconType['height']); let rectX = that.iconX + Math.ceil(that.iconType['width'] / 4) * 3; let rectY = that.iconY + (that.iconType['height'] / 3) * 2; let nameWidth = 0, rectHeight = 20; // 矩形的高 let textObj: any = stringTypeNum(that.rectContent); nameWidth = textObj['numberAndEngNum'] * 7 + 12 * textObj['chineseNum'] + 6 * textObj['otherNum']; let value: any = getRectWidth(that.iconType['type'], nameWidth, that.rectContent); let rect = new Rect(rectX, rectY, value['rectWidth'], rectHeight, value['rectContent'], 'black'); rect.drawRect(); // 画矩形 }; // 返回图标左边中心的左边和图标右边中心的坐标 iconInfo['leftCoordinate'] = { leftX: that.iconX, leftY: that.iconY + that.iconType['height'] / 2 }; iconInfo['rightCoordinate'] = { rightX: that.iconX + that.iconType['width'], rightY: that.iconY + that.iconType['height'] / 2 }; iconInfo['icon'] = that.iconType; return iconInfo; } } export { getCanvasContext, Text, Rect, Line, Arrow, Icon };