canvas画图,时间轴刻度标签

在时间轴上显示对应时间段的标签(状态)

在这里插入图片描述


<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>

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要画出一个有刻度的 y ,可以按照以下步骤操作: 1. 首先确定 y 的起点和终点坐标,例如 (x0, y0) 和 (x0, y1)。 2. 然后确定 y 的长度,即 y 上需要画多少个刻度。假设需要画 n 个刻度。 3. 计算每个刻度之间的间隔,即 y 的长度除以刻度数目 n。假设刻度间隔为 a。 4. 从起点 (x0, y0) 开始,向上每隔一个间隔 a,画一条长度为 b 的直线,作为刻度线。可以使用 canvas 的 lineTo() 方法画直线。 5. 画完所有的刻度线之后,可以添加刻度值。例如,可以在每个刻度线的上方或下方标注刻度值。 下面是一个简单的示例代码,可以画出一个有刻度的 y : ```javascript // canvas 画布 const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); // y 起点和终点坐标 const x0 = 50; const y0 = 50; const y1 = 350; // y 上的刻度数 const n = 10; // 刻度间隔和长度 const a = (y1 - y0) / n; const b = 5; // 画 y ctx.beginPath(); ctx.moveTo(x0, y0); ctx.lineTo(x0, y1); ctx.stroke(); // 画刻度线和刻度值 for (let i = 0; i < n; i++) { const y = y0 + i * a; ctx.beginPath(); ctx.moveTo(x0 - b, y); ctx.lineTo(x0, y); ctx.stroke(); ctx.fillText(i + 1, x0 - b * 3, y + a / 2); } ``` 这段代码会在 canvas 上画出一个从 (50, 50) 到 (50, 350) 的 y ,共有 10 个刻度刻度间隔为 (350 - 50) / 10 = 30,刻度线长度为 5。刻度值会显示在每个刻度线的左侧。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值