需求:
1、 根据后端返回的数据,动态绘制出信令图
2、根据 dataStatus 返回值: 0 和 1, 判断 文字内容的颜色,0:#000,1:red
3.、根据 lineType 返回值: 0 和 1, 判断 箭头线的显示 是实线、虚线
4、根据返回的文字内容的换行符:“\r\n” 自动换行 (这步比较难,得计算高度)
最后的效果图大概是这样的:
一、标题的动态获取
1-1、如果后端给你返回的标题是随机顺序的,这里需要根据全部标题数组做一下排序。
// 全部标题数组:
titletypeArr: ['ATP', 'MT', 'BTS', 'BSC', 'MSC', 'RBC'],
// 后端返回的随机标题数组:
resultTitle: ['MT', 'ATP' ]
// 处理方法
this.typeArr = this.titletypeArr.filter(item => this.resultTitle.indexOf(item) !== -1)
二、canvas绘制初始化
// 初始化加载
initData() {
var mycanvas = document.getElementById("myCanvas");
this.canvas = mycanvas;
var context = mycanvas.getContext("2d");
// 动态设置宽高一定要在 myCanvas 节点添加之后
document.getElementById("myCanvas").width = this.typeArr.length * 320 - 120;
document.getElementById("myCanvas").style.background = "#fff";
const minHeight = window.innerHeight - 180;
if (this.xlArr.length > 0) {
document.getElementById("myCanvas").height =
30 * this.xlArr.length + 80 < minHeight
? minHeight
: 30 * this.xlArr.length + 80;
} else {
document.getElementById("myCanvas").height = minHeight;
}
var height = this.paddingTop + 62; // 初始值
this.xlArr.map((v, i) => {
const k = this.typeArr.indexOf(v.startDataDir);
const j = this.typeArr.indexOf(v.endDataDir);
context.font = '13px "微软雅黑"'; // 设置字体
// 时间文字
context.fillStyle = '#000' // 时间颜色
context.fillText(v.recTime.split(' ')[1], 40, height);
// 箭头
this.paintArr(
v,
[this.gapX * k + this.paddingLeft, height],
[this.gapX * j + this.paddingLeft, height],
k < j ? "right" : "left",
context
);
var maxWidth = 260; // 最大宽度,超过这个宽度会自动换行
var words = v.showInfo.split("\r\n");
// 文字自动换行
this.wrapText(
v,
context,
words,
this.gapX * (k < j ? k : j) + this.paddingLeft,
height - 10,
maxWidth,
this.lineHeight
);
if (i < this.xlArr.length - 1) {
let nextWords = this.xlArr[i + 1].showInfo.split("\r\n");
height += (this.lineHeight * (words.length + nextWords.length)) / 2 + 30;
} else {
height += this.lineHeight * words.length + 30;
}
// console.log(height, "height")
})
// 画虚线以及标题
this.typeArr.map((v, i) => {
this.paintText(context, v, i);
setTimeout(() => {
this.drawDashed(context, i);
}, 300)
})
// document.getElementById('container').onscroll = (e) => {
// // console.log('e:', e.target)
// this.left = e.target.scrollLeft
// }
// 屏蔽所有页面 右键菜单
// document.oncontextmenu = (event) => {
// event.returnValue = false
// }
// 屏蔽当前页面 右键菜单
// document.getElementById('container').oncontextmenu = (event) => {
// event.returnValue = false
// }
}
三、绘制箭头
// 箭头
paintArr(item, s, t, direction, ctx) {
ctx.beginPath()
ctx.lineWidth = 1
if (item.dataStatus == 1) {
ctx.strokeStyle = 'red'
} else {
ctx.strokeStyle = '#000' // 箭头线的颜色
}
if (item.lineType === 1) {
ctx.setLineDash([5, 2]); // 虚线
}
ctx.moveTo(s[0], s[1])
ctx.lineTo(t[0], t[1])
ctx.stroke()
ctx.closePath()
ctx.beginPath()
if (direction === 'right') {
ctx.moveTo(t[0] - 10, t[1] + 3)
ctx.lineTo(t[0], t[1])
ctx.lineTo(t[0] - 10, t[1] - 3)
} else {
ctx.moveTo(t[0] + 10, t[1] - 3)
ctx.lineTo(t[0], t[1])
ctx.lineTo(t[0] + 10, t[1] + 3)
}
// ctx.closePath()
ctx.stroke()
// ctx.fill()
},
四、绘制 标题列的虚线
// 标题列的虚线
drawDashed(ctx, i) {
ctx.beginPath()
ctx.lineWidth = 1
ctx.strokeStyle = '#696969' // '#FF8080'//虚线的颜色
ctx.setLineDash([5, 2])
ctx.moveTo(320 * i + this.paddingLeft, this.paddingTop + 40);
ctx.lineTo(320 * i + this.paddingLeft, 400 * this.typeArr.length);
ctx.fill()
ctx.stroke()
ctx.closePath()
},
五、文字自动换行 遇到换行符换行
// 文字自动换行 遇到换行符换行,并且超出最大宽度换行,只计算了最多显示7行的情况,超出7行得再计算
wrapText(item, context, words, x, y, maxWidth, lineHeight) {
// console.log(words, "words")
let originY = y;
let len = words.length;
let rectWidth = 0;
for (var n = 0; n < len; n++) {
// 不超出一行
var testWidth = context.measureText(words[n]).width;
if (testWidth < maxWidth) {
if (rectWidth < testWidth) {
rectWidth = testWidth;
}
}
}
// 在上面循环计算出文字实际最宽的位置,画出背景色遮挡箭头
// 画背景色遮盖箭头, 背景色自己调,跟画布统一就行
context.fillStyle = "#fff"; // 背景颜色
context.fillRect(