Canvas画图之直线带箭头封装

其实原理很简单,只不过要我们回归一下下学生时代学习的三角函数
原理后面再补充,我先上代码

line.js --------- 这个文件是用来封装canvas对象的

/*
 *  x1,y1 第一个点的坐标
 *  x2,y2 第二个点的坐标
 *  type 箭头的方向
 *  color 整体颜色 (如果需要箭头和直线颜色分离的话,再加一个参数)
 *  arrows 是否需要箭头 true代表需要
 */
class Line {
  constructor(x1, y1, x2, y2, type, color, arrows) {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.type = type;
    this.color = color;
    this.arrows = arrows;
  }
  draw (ctx) {
    // 设置箭头样式
    ctx.strokeStyle = this.color;
    ctx.fillStyle = this.color;
    ctx.lineWidth = 1;

    // 画线
    ctx.beginPath();
    ctx.moveTo(this.x1, this.y1);
    ctx.lineTo(this.x2, this.y2);
    ctx.stroke();
    if (this.arrows) {
      this.drawHasArrow(ctx);
    }
  }
  drawHasArrow (ctx) {
    let d = 6;
    let angle = 15;
    if (this.type == 0) {
      // 画向上的箭头
      this.drawArrowhead(ctx, this.x2, this.y2, this.x2 - Math.tan(angle) * d, this.y2 + d, this.x2 + Math.tan(angle) * d, this.y2 + d)
    } else if (this.type == 1) {
      // 画向下的箭头
      this.drawArrowhead(ctx, this.x2, this.y2, this.x1 - Math.tan(angle) * d, this.y2 - d, this.x1 + Math.tan(angle) * d, this.y2 - d)
    } else {
      // 画向右的箭头
      this.drawArrowhead(ctx, this.x2, this.y2, this.x2 - d, this.y1 - Math.tan(angle) * d, this.x2 - d, Math.tan(angle) * d + this.y1)
    }
  }
  drawArrowhead (ctx, x, y, x3, y3, x4, y4) {
    ctx.save();
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x3, y3);
    ctx.lineTo(x4, y4);
    ctx.closePath();
    ctx.restore();
    ctx.fill();
  }
}
export default Line;

我的使用方法如下(例子使用的框架是vue2)
我是用的是批量画线的方法,当然你也可以画单个线,如果画单个线,只需要把drawLine的for循环里面的代码提出来,改下参数就行。

<script>
import Line from "./Line.js";
export default {
  data () {
    return {
      c: null,
      ctx: null,
      // 初始坐标
      initX: 100,
      initY: 22,
      lineInfo: {}
    }
  },
  methods: {
    canvasInit () {
      this.c = this.$refs.myRelativeCanvas;
      // 这里是设置canvas画布的宽高,我是需要做成自适应宽高的,所以我依赖"ete-relative-box"这个自适应dom
      this.c.width = document.getElementsByClassName("ete-relative-box")[0].clientWidth * 0.95
      this.c.height = document.getElementsByClassName("ete-relative-box")[0].clientHeight * 0.95
      this.ctx = this.c.getContext("2d");
    },
    drawLine () {
      this.initLineInfo();
      for (let key in this.lineInfo) {
        let line = new Line(
          this.lineInfo[key].x1,
          this.lineInfo[key].y1,
          this.lineInfo[key].x2,
          this.lineInfo[key].y2,
          this.lineInfo[key].type,
          this.lineInfo[key].color,
          this.lineInfo[key].arrows
        );
        line.draw(this.ctx);
      }
    },
    // 这个函数可以用来批量画
    initLineInfo () {
      this.lineInfo = {
        solved_research: {
          x1: this.initX + 260,
          y1: this.initY + 45,
          x2: this.initX + 260,
          y2: this.initY + 194,
          type: 1,
          arrows: true,
          color: "#b7b7b7de"
        },
        research_normal: {
          x1: this.initX + 320,
          y1: this.initY + 210,
          x2: this.initX + 490,
          y2: this.initY + 210,
          type: 2,
          arrows: true,
          color: "#706368"
        },
        doa_air_closed: {
          x1: this.initX + 1290,
          y1: this.initY + 301,
          x2: this.initX + 1290,
          y2: this.initY + 225,
          type: 0,
          arrows: true,
          color: "#b7b7b7de"
        },
        research_air_air_up: {
          x1: this.initX + 430,
          y1: this.initY + 210,
          x2: this.initX + 430,
          y2: this.initY + 119,
          type: 1,
          arrows: false,
          color: "#4cadab"
        }
      }
    }
  },
  created () {
    this.$nextTick(function () {
      this.canvasInit();
      this.drawLine();
    })
  }
}
</script>
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Canvas上绘制双线箭头直线,你可以按照以下步骤进行操作: 1. 获取到Canvas元素的引用,并创建一个2D上下文对象。 ```javascript const canvas = document.getElementById("myCanvas"); const ctx = canvas.getContext("2d"); ``` 2. 设置线条的样式,包括线宽和颜色。 ```javascript ctx.lineWidth = 2; ctx.strokeStyle = "black"; ``` 3. 绘制直线的起点和终点。 ```javascript const startX = 50; const startY = 50; const endX = 200; const endY = 50; ctx.beginPath(); ctx.moveTo(startX, startY); ctx.lineTo(endX, endY); ctx.stroke(); ``` 4. 绘制箭头。可以通过绘制三角形来模拟箭头的形状。 ```javascript // 绘制箭头的长度和宽度 const arrowLength = 10; const arrowWidth = 6; // 计算箭头的角度和两侧点的坐标 const angle = Math.atan2(endY - startY, endX - startX); const arrowPoint1X = endX - arrowLength * Math.cos(angle - Math.PI / 6); const arrowPoint1Y = endY - arrowLength * Math.sin(angle - Math.PI / 6); const arrowPoint2X = endX - arrowLength * Math.cos(angle + Math.PI / 6); const arrowPoint2Y = endY - arrowLength * Math.sin(angle + Math.PI / 6); // 绘制箭头 ctx.beginPath(); ctx.moveTo(endX, endY); ctx.lineTo(arrowPoint1X, arrowPoint1Y); ctx.moveTo(endX, endY); ctx.lineTo(arrowPoint2X, arrowPoint2Y); ctx.stroke(); // 绘制箭头底部闭合 ctx.beginPath(); ctx.moveTo(arrowPoint1X, arrowPoint1Y); ctx.lineTo(arrowPoint2X, arrowPoint2Y); ctx.lineTo(endX, endY); ctx.closePath(); ctx.fill(); ``` 完整的代码示例如下: ```javascript const canvas = document.getElementById("myCanvas"); const ctx = canvas.getContext("2d"); ctx.lineWidth = 2; ctx.strokeStyle = "black"; const startX = 50; const startY = 50; const endX = 200; const endY = 50; ctx.beginPath(); ctx.moveTo(startX, startY); ctx.lineTo(endX, endY); ctx.stroke(); const arrowLength = 10; const arrowWidth = 6; const angle = Math.atan2(endY - startY, endX - startX); const arrowPoint1X = endX - arrowLength * Math.cos(angle - Math.PI / 6); const arrowPoint1Y = endY - arrowLength * Math.sin(angle - Math.PI / 6); const arrowPoint2X = endX - arrowLength * Math.cos(angle + Math.PI / 6); const arrowPoint2Y = endY - arrowLength * Math.sin(angle + Math.PI / 6); ctx.beginPath(); ctx.moveTo(endX, endY); ctx.lineTo(arrowPoint1X, arrowPoint1Y); ctx.moveTo(endX, endY); ctx.lineTo(arrowPoint2X, arrowPoint2Y); ctx.stroke(); ctx.beginPath(); ctx.moveTo(arrowPoint1X, arrowPoint1Y); ctx.lineTo(arrowPoint2X, arrowPoint2Y); ctx.lineTo(endX, endY); ctx.closePath(); ctx.fill(); ``` 这样就可以在Canvas上绘制双线箭头直线了。记得根据你的需求修改起点和终点的坐标。希望对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值