需求:
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(
x + this.gapX / 2 - rectWidth / 2 - 4,
originY,
rectWidth + 6,
lineHeight
); // 填充黄色背景
for (var n = 0; n < len; n++) {
// 不超出一行
var testWidth = context.measureText(words[n]).width;
if (testWidth < maxWidth) {
// console.log(words[n], 1);
let currentY = y;
if (len === 1) {
currentY = y + 14;
} else if (len === 2) {
currentY = y + 2;
} else if (len === 3) {
currentY = y - 6;
} else if (len === 4) {
currentY = y - 18;
} else if (len === 5) {
currentY = y - 28;
} else if (len === 6) {
currentY = y - 38;
} else if (len === 7) {
currentY = y - 48;
}
if (item.dataStatus == 1) {
context.fillStyle = 'red'
} else {
context.fillStyle = '#000' // 字体颜色
}
// context.fillStyle = "#000"; // 字体颜色
context.fillText(words[n], x + this.gapX / 2 - testWidth / 2, currentY);
if (len > 1) {
y += lineHeight;
}
} else {
console.log(words[n], 2);
// 文字超出一行,需要换行展示
// 实际大于页面width font-size: 12, 计算出显示多少行
let singleWordwith = 13;
// 计算一行显示的最大字数,以及显示多少行
let len = Math.floor(maxWidth / singleWordwith);
let lineCount = Math.ceil(words[n].length / len);
for (let j = 0; j <= lineCount; j++) {
// 截取出每行显示的字
let word = words[n].substr(j * len, len);
let wordWidth = context.measureText(word).width;
// 写入画布
// 画背景色遮盖箭头, 背景色自己调,跟画布统一就行
context.fillStyle = "#fff";
context.fillRect(
x + this.gapX / 2 - wordWidth / 2,
y - 4,
wordWidth,
lineHeight
); // 填充黄色背景
let currentY = y;
if (lineCount === 2) {
currentY = y + 2;
} else if (lineCount === 3) {
currentY = y - 6;
} else if (lineCount === 4) {
currentY = y - 18;
} else if (lineCount === 5) {
currentY = y - 28;
} else if (lineCount === 6) {
currentY = y - 38;
} else if (lineCount === 7) {
currentY = y - 48;
}
if (item.dataStatus == 1) {
context.fillStyle = 'red'
} else {
context.fillStyle = '#000' // 字体颜色
}
// context.fillStyle = "#000";
context.fillText(word, x + this.gapX / 2 - wordWidth / 2, currentY);
y += lineHeight; // 换行
}
}
}
},
六、模拟后端返回的数据
// signalTimeData: [
// {
// startDataDir: "ATP",
// endDataDir: "MT",
// recTime: '2023-09-10 09:12:48',
// showInfo: "M136\r\nT_Train=9340940ms\r\nDT:16",
// dataDir: 0,
// dataDirStr: "上行",
// lineType: 0,
// dataStatus: 0
// },
// {
// startDataDir: "MT",
// endDataDir: "ATP",
// recTime: '2023-09-10 09:12:49',
// showInfo: "M24\r\nT_Train=9341070ms",
// dataDir: 1,
// dataDirStr: "下行",
// lineType: 0,
// dataStatus: 0
// },
// {
// startDataDir: "ATP",
// endDataDir: "MT",
// recTime: '2023-09-10 09:13:06',
// showInfo: "M136\r\nT_Train=9358940ms\r\nDT:19\r\n此时,M24之后ATP发送3条APDU",
// dataDir: 0,
// dataDirStr: "上行",
// lineType: 0,
// dataStatus: 1
// },
// {
// startDataDir: "MT",
// endDataDir: "ATP",
// recTime: '2023-09-10 09:13:07',
// showInfo: "AK:20\r\n此时,M24之后RBC发送3条AK,无APDU",
// dataDir: 1,
// dataDirStr: "下行",
// lineType: 0,
// dataStatus: 1
// },
// {
// startDataDir: "ATP",
// endDataDir: "MT",
// recTime: '2023-09-10 09:13:08',
// showInfo: "TPDU_DR/SaPDU_D",
// dataDir: 0,
// dataDirStr: "上行",
// lineType: 0,
// dataStatus: 1
// },
// {
// startDataDir: "MT",
// endDataDir: "ATP",
// recTime: '2023-09-10 09:13:09',
// showInfo: "TPDU_DC",
// dataDir: 1,
// dataDirStr: "下行",
// lineType: 0,
// dataStatus: 0
// },
// {
// startDataDir: "ATP",
// endDataDir: "MT",
// recTime: "2023-09-10 09:13:09",
// showInfo: "DISC",
// dataDir: 0,
// dataDirStr: "上行",
// lineType: 0,
// dataStatus: 0
// },
// {
// startDataDir: "MT",
// endDataDir: "ATP",
// recTime: "2023-09-10 09:13:09",
// showInfo: "NO CARRIER",
// dataDir: 1,
// dataDirStr: "下行",
// lineType: 0,
// dataStatus: 0
// }
// ],
全部代码如下:
<template>
<!-- :width="dialogWidth" -->
<vxe-modal v-model="sigModal" :title="titles" width="1200" min-width="550" :height="dialogHeight" :position="{ top: '3vh' }" @close="closeEvent" resize destroy-on-close>
<div class="con">
<el-row style="margin-bottom:10px">
<el-button type="primary" icon="el-icon-upload" @click="screenShot()">上传</el-button>
</el-row>
<div ref="screen" :style="{width: canvasWidth, height: canvasHeight}">
<canvas id="myCanvas" :width="canvasWidth" :height="canvasHeight">
你的浏览器还不支持canvas
</canvas>
</div>
</div>
</vxe-modal>
</template>
<script>
import html2canvas from 'html2canvas'
import { DownLoadFromTime } from '@/utils/times.js'
import { get_signallInfo } from '@/api/c3/offlineImportant.js'
import axios from 'axios'
export default {
data() {
return {
uploadId: '',
titles: '信令图',
dialogWidth: '90%',
dialogHeight: '92%',
sigModal: false,
// 'ATP'-----'MT'------------ 'BTS'-------'BSC'----'MSC'------ 'RBC'
// Igsmr-R Um_AMS/Um_BMS Abis A PRI
resultTitle: ['ATP', 'MT'], // 后台返回的随机顺序
titletypeArr: ['ATP', 'MT', 'BTS', 'BSC', 'MSC', 'RBC'],
typeArr: [],
canvasWidth: '1080px',
canvasHeight: (window.innerHeight) - 170 + 'px',
minHeight: (window.innerHeight) - 170,
// signalTimeData: [
// {
// startDataDir: "ATP",
// endDataDir: "MT",
// recTime: '2023-09-10 09:12:48',
// showInfo: "M136\r\nT_Train=9340940ms\r\nDT:16",
// dataDir: 0,
// dataDirStr: "上行",
// lineType: 0,
// dataStatus: 0
// },
// {
// startDataDir: "MT",
// endDataDir: "ATP",
// recTime: '2023-09-10 09:12:49',
// showInfo: "M24\r\nT_Train=9341070ms",
// dataDir: 1,
// dataDirStr: "下行",
// lineType: 0,
// dataStatus: 0
// },
// {
// startDataDir: "ATP",
// endDataDir: "MT",
// recTime: '2023-09-10 09:13:06',
// showInfo: "M136\r\nT_Train=9358940ms\r\nDT:19\r\n此时,M24之后ATP发送3条APDU",
// dataDir: 0,
// dataDirStr: "上行",
// lineType: 0,
// dataStatus: 1
// },
// {
// startDataDir: "MT",
// endDataDir: "ATP",
// recTime: '2023-09-10 09:13:07',
// showInfo: "AK:20\r\n此时,M24之后RBC发送3条AK,无APDU",
// dataDir: 1,
// dataDirStr: "下行",
// lineType: 0,
// dataStatus: 1
// },
// {
// startDataDir: "ATP",
// endDataDir: "MT",
// recTime: '2023-09-10 09:13:08',
// showInfo: "TPDU_DR/SaPDU_D",
// dataDir: 0,
// dataDirStr: "上行",
// lineType: 0,
// dataStatus: 1
// },
// {
// startDataDir: "MT",
// endDataDir: "ATP",
// recTime: '2023-09-10 09:13:09',
// showInfo: "TPDU_DC",
// dataDir: 1,
// dataDirStr: "下行",
// lineType: 0,
// dataStatus: 0
// },
// {
// startDataDir: "ATP",
// endDataDir: "MT",
// recTime: "2023-09-10 09:13:09",
// showInfo: "DISC",
// dataDir: 0,
// dataDirStr: "上行",
// lineType: 0,
// dataStatus: 0
// },
// {
// startDataDir: "MT",
// endDataDir: "ATP",
// recTime: "2023-09-10 09:13:09",
// showInfo: "NO CARRIER",
// dataDir: 1,
// dataDirStr: "下行",
// lineType: 0,
// dataStatus: 0
// }
// ],
xlArr: [],
canvas: null,
left: 0,
paddingLeft: 120,
paddingTop: 20,
gapX: 320, // x轴间隔
gapY: 90, // y轴间隔
lineHeight: 20 // 行高
}
},
created() {
// this.typeArr = this.titletypeArr.filter(item => this.resultTitle.indexOf(item) !== -1)
// this.xlArr = this.signalTimeData
// this.canvasWidth = (this.typeArr.length * 320) - 120 + 'px'
this.fnHight()
window.addEventListener('resize', this.fnHight, true)
},
mounted() {},
destroyed() {
this.$destroy()
window.removeEventListener('resize', this.fnHight, true)
},
methods: {
// 获取信令图数据
getSignallList(accidentId) {
let parmsData = {
accidentId: accidentId
}
get_signallInfo(parmsData).then(res => {
if (res.status === 200) {
if (res.data.code === 0) {
if (res.data.data) {
this.resultTitle = res.data.data.interfaceTypes
this.typeArr = this.titletypeArr.filter(item => this.resultTitle.indexOf(item) !== -1)
this.xlArr = res.data.data.mtDiagramInfoVoList
this.canvasWidth = (this.typeArr.length * 320) - 120 + 'px'
} else {
this.$XModal.message({ content: '未查询到信令图数据.', status: 'warning' })
}
} else {
this.$XModal.message({ content: res.message, status: 'error' })
}
}
})
},
// 截屏
screenShot() {
html2canvas(this.$refs.screen, {
backgroundColor: '#FFFFFF',
useCORS: true
}).then((canvas) => {
// 获取到canvas
canvas.toBlob(blob => {
// 将二进制对象的内容 转成file
const file = new File([blob], Date.now() + '.png', { type: 'image/png' })
const formData = new FormData()
formData.append('file', file)
formData.append('uploadId', this.uploadId)
// 发起请求
axios({
headers: {
'Authorization': this.$store.state.user.token,
'showInfo-Type': 'multipart/form-data'
},
method: 'post',
url: '/api/offline/analysisContent/uploadReportPdf',
data: formData,
}).then((res) => {
// 上传成功
if (res.status === 200) {
this.$XModal.message({ content: '上传成功', status: 'success'})
this.$emit('sumitSuccess', 'ok')
}
}).catch((error) => {
// 上传失败 执行对应操作
this.$XModal.message({ content: '上传失败', status: 'error' })
})
}, 'image/png')
if (navigator.msSaveBlob) { // IE10+
let blob = canvas.msToBlob();
return navigator.msSaveBlob(blob, name);
} else {
let imageurl = canvas.toDataURL('image/png')
const newTime = DownLoadFromTime(new Date())
//这里需要自己选择命名规则
let imagename = '信令图_' + 'G1884' + '_' + newTime
this.fileDownload(imageurl, imagename)
}
})
},
// 下载截屏图片
fileDownload(downloadUrl, downloadName) {
let aLink = document.createElement("a")
aLink.style.display = "none"
aLink.href = downloadUrl
aLink.download = `${downloadName}.png`
// 触发点击-然后移除
document.body.appendChild(aLink)
aLink.click()
document.body.removeChild(aLink)
},
closeEvent() {
this.sigModal = false
},
fnHight() {
setTimeout(() => {
this.minHeight = (window.innerHeight) - 170
}, 300)
},
// 标题的边框
paintText(ctx, text, i) {
// ctx.fillStyle = '#FEFECE'
ctx.fillStyle = '#FFF'
ctx.fillRect(320 * i + this.paddingLeft - 30, this.paddingTop, 60, 30); // 填充黄色背景
// ctx.strokeStyle = 'red'
ctx.strokeStyle = '#000' // '#A80036' // 标题的边框颜色
ctx.strokeRect(320 * i + this.paddingLeft - 30, this.paddingTop, 60, 30); // 设置边框
ctx.font = '12px "微软雅黑"' // 设置字体
ctx.textBaseline = 'bottom' // 设置字体底线对齐绘制基线
ctx.textAlign = 'left' // 设置字体对齐的方式
ctx.fillStyle = 'Black'
ctx.fillText(text, 320 * i + this.paddingLeft - 10, this.paddingTop + 22); // 填充文字标题
// ctx.closePath()
},
// 箭头
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(
x + this.gapX / 2 - rectWidth / 2 - 4,
originY,
rectWidth + 6,
lineHeight
); // 填充黄色背景
for (var n = 0; n < len; n++) {
// 不超出一行
var testWidth = context.measureText(words[n]).width;
if (testWidth < maxWidth) {
// console.log(words[n], 1);
let currentY = y;
if (len === 1) {
currentY = y + 14;
} else if (len === 2) {
currentY = y + 2;
} else if (len === 3) {
currentY = y - 6;
} else if (len === 4) {
currentY = y - 18;
} else if (len === 5) {
currentY = y - 28;
} else if (len === 6) {
currentY = y - 38;
} else if (len === 7) {
currentY = y - 48;
}
if (item.dataStatus == 1) {
context.fillStyle = 'red'
} else {
context.fillStyle = '#000' // 字体颜色
}
// context.fillStyle = "#000"; // 字体颜色
context.fillText(words[n], x + this.gapX / 2 - testWidth / 2, currentY);
if (len > 1) {
y += lineHeight;
}
} else {
console.log(words[n], 2);
// 文字超出一行,需要换行展示
// 实际大于页面width font-size: 12, 计算出显示多少行
let singleWordwith = 13;
// 计算一行显示的最大字数,以及显示多少行
let len = Math.floor(maxWidth / singleWordwith);
let lineCount = Math.ceil(words[n].length / len);
for (let j = 0; j <= lineCount; j++) {
// 截取出每行显示的字
let word = words[n].substr(j * len, len);
let wordWidth = context.measureText(word).width;
// 写入画布
// 画背景色遮盖箭头, 背景色自己调,跟画布统一就行
context.fillStyle = "#fff";
context.fillRect(
x + this.gapX / 2 - wordWidth / 2,
y - 4,
wordWidth,
lineHeight
); // 填充黄色背景
let currentY = y;
if (lineCount === 2) {
currentY = y + 2;
} else if (lineCount === 3) {
currentY = y - 6;
} else if (lineCount === 4) {
currentY = y - 18;
} else if (lineCount === 5) {
currentY = y - 28;
} else if (lineCount === 6) {
currentY = y - 38;
} else if (lineCount === 7) {
currentY = y - 48;
}
if (item.dataStatus == 1) {
context.fillStyle = 'red'
} else {
context.fillStyle = '#000' // 字体颜色
}
// context.fillStyle = "#000";
context.fillText(word, x + this.gapX / 2 - wordWidth / 2, currentY);
y += lineHeight; // 换行
}
}
}
},
// 初始化加载
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
// }
}
}
}
</script>
<style lang="scss" scoped>
.con {
position: relative;
}
.topTitle{
position: absolute;
background: #fff;
top: 38px;
padding-left: 15px;
// width: 2580px;
display: flex;
li {
display: inline-block;
width: 320px;
margin: 3px 0;
}
li:nth-last-child(1) {
width: 100px;
}
span {
// border: 1px solid #A80036;
border: 1px solid #000;
padding: 5px 10px;
// background-color: #FEFECE;
background-color: #fff;
display: inline-block;
}
}
#container {
// overflow-x: scroll;
// overflow-y: scroll;
overflow: hidden;
}
#canvas {
display: block;
background-color: #fff;
}
</style>