在时间轴上显示对应时间段的标签(状态)
<template>
<div class="line_body">
<canvas id="line" height="300"> </canvas>
</div>
</template>
<script>
export default {
data() {
return {
lineList: [
{
time: '2020/02/08',
info: '获取资质',
},
{
time: '2020/07/08',
info: '获取资质',
},
{
time: '2020/12/08',
info: '备案',
},
{
time: '2020/12/09',
info: '备案',
},
{
time: '2021/03/08',
info: '年检',
},
{
time: '2021/04/15',
info: '事前变更',
},
{
time: '2021/08/15',
info: '事前变更',
},
{
time: '2022/03/12',
info: '备案',
},
{
time: '2022/03/13',
info: '备案',
},
{
time: '2022/03/20',
info: '备案',
},
],
};
},
mounted() {
this.initLine();
},
methods: {
toTimeStamp(dateString) {
// dateString例如:'2022-03-05'
// 例如返回:1646611200000
return new Date(dateString) - 0;
},
getDistanceDays(date1, date2) {
// date1例如:'2022-03-05',date2例如:'2022-03-06'
const dateTimeStamp1 = this.toTimeStamp(date1);
const dateTimeStamp2 = this.toTimeStamp(date2);
let max = '';
let min = '';
if (dateTimeStamp1 > dateTimeStamp2) {
max = dateTimeStamp1;
min = dateTimeStamp2;
} else {
max = dateTimeStamp2;
min = dateTimeStamp1;
}
// 例如返回:'1'
return (max - min) / (24 * 60 * 60 * 1000);
},
drawText(t, x, y, w, context) {
const chr = t.split('');
let temp = '';
const row = [];
context.fillStyle = 'white';
context.textBaseline = 'middle';
context.font = "20px '微软雅黑'";
for (let a = 0; a < chr.length; a += 1) {
if (context.measureText(temp).width < w) {
console.log(2222);
} else {
row.push(temp);
temp = '';
}
temp += chr[a];
}
row.push(temp);
for (let b = 0; b < row.length; b += 1) {
context.fillText(row[b], x, y + (b + 1) * 20);
}
},
initLine() {
const canvas = document.getElementById('line');
// if (canvas.width < window.innerWidth) {
// canvas.width = window.innerWidth;
// }
// 刻度长度一天
let count = 0;
let num = 0;
// 防止挤压 最短几天
const jyNum = 8;
const unitLen = 5;
const len = this.lineList.length;
const canvasLen = this.getDistanceDays(this.lineList[0].time, this.lineList[len - 1].time);
// this.lineList.forEach((item, index) => {
// const num = this.getDistanceDays(this.lineList[index].time, this.lineList[index + 1].time);
// console.log(count);
// });
for (let j = 0; j < this.lineList.length; j += 1) {
if (j === this.lineList.length - 1) {
num = 100;
} else {
num = this.getDistanceDays(this.lineList[j].time, this.lineList[j + 1].time);
}
// 判断数据中有多少小于 8 天的数据,防止挤压
if (num < jyNum) {
count += 1;
}
}
canvas.width = canvasLen * unitLen + 200 + count * 120;
// if (canvas.height < window.innerHeight) {
// canvas.height = 250;
// // window.innerHeight
// }
// 获得 2d 上下文对象
const ctx = canvas.getContext('2d');
// let daylinelen = 0;
let i = 0;
let lastDaylen = 100;
let days = 0;
for (i = 0; i < this.lineList.length; i += 1) {
// 直线
ctx.beginPath();
if (i === this.lineList.length - 1) {
days = 100;
} else {
days = this.getDistanceDays(this.lineList[i].time, this.lineList[i + 1].time);
}
if (i === 0) {
ctx.moveTo(100, 225);
ctx.lineTo(days * unitLen + 100, 225);
} else {
ctx.moveTo(lastDaylen, 225);
ctx.lineTo(days * unitLen, 225);
}
// 每个月约120 每天小刻度为40
ctx.lineWidth = 2;
ctx.strokeStyle = '#ccc';
ctx.stroke();
// 刻度
ctx.beginPath();
if (i === 0) {
ctx.moveTo(100, 215);
ctx.lineTo(100, 230);
} else {
ctx.moveTo(lastDaylen, 215);
ctx.lineTo(lastDaylen, 230);
}
// ctx.moveTo(lastDaylen, 215); // x,y
// 日期刻度
ctx.lineWidth = 5;
ctx.strokeStyle = 'black';
ctx.stroke();
// 刻度下日期
ctx.beginPath();
ctx.fillStyle = 'black';
ctx.font = "16px '微软雅黑'";
if (i === 0) {
ctx.fillText(this.lineList[i].time, 50, 260, 100); // 绘制 "空心" 文字
} else {
ctx.fillText(this.lineList[i].time, lastDaylen - 50, 260, 100); // 绘制 "空心" 文字
}
ctx.stroke();
// info Tag 标签
ctx.beginPath();
// eslint-disable-next-line default-case
switch (this.lineList[i].info) {
case '获取资质':
ctx.fillStyle = 'rgb(250, 200, 88)';
break;
case '年检':
ctx.fillStyle = 'rgb(250, 200, 88)';
break;
case '备案':
ctx.fillStyle = 'rgb(84, 112, 198)';
break;
case '事前变更':
ctx.fillStyle = 'rgb(145, 204, 117)';
break;
}
// ctx.fillStyle = 'rgb(250, 200, 88)';
const x = 100;
const y = 20;
if (i === 0) {
ctx.fillRect(60, 70, 80, 120);
} else {
ctx.fillRect(lastDaylen - 40, 70, 80, 120);
}
ctx.stroke();
ctx.beginPath();
ctx.lineWidth = 1;
if (i === 0) {
ctx.moveTo(95, 190);
ctx.lineTo(100, 196);
ctx.lineTo(105, 190);
ctx.lineTo(95, 190);
// ctx.fillText(`获取\n 资质`, 70, 150, 70);
this.drawText(this.lineList[i].info, 80, 100, 40, ctx);
} else {
ctx.moveTo(lastDaylen - 5, 190);
ctx.lineTo(lastDaylen, 196);
ctx.lineTo(lastDaylen + 5, 190);
ctx.lineTo(lastDaylen - 5, 190);
this.drawText(this.lineList[i].info, lastDaylen - 20, 100, 40, ctx);
}
// eslint-disable-next-line default-case
switch (this.lineList[i].info) {
case '获取资质':
ctx.fillStyle = 'rgb(250, 200, 88)';
ctx.strokeStyle = 'rgb(250, 200, 88)';
break;
case '年检':
ctx.fillStyle = 'rgb(250, 200, 88)';
ctx.strokeStyle = 'rgb(250, 200, 88)';
break;
case '备案':
ctx.fillStyle = 'rgb(84, 112, 198)';
ctx.strokeStyle = 'rgb(84, 112, 198)';
break;
case '事前变更':
ctx.fillStyle = 'rgb(145, 204, 117)';
ctx.strokeStyle = 'rgb(145, 204, 117)';
break;
}
ctx.fill();
ctx.stroke();
ctx.closePath();
if (days < jyNum) {
lastDaylen += 120;
} else {
lastDaylen += days * unitLen;
}
}
},
},
};
</script>
<style scoped>
.line_body {
width: 100%;
overflow: auto;
}
::-webkit-scrollbar {
width: 200px !important;
height: 40px;
}
</style>