canvas画箭头线

箭头线

vue+uni-app+canvas 画带箭头可拖动的线段

<template>
  <div>
    <canvas ref="canvas" class="canvas" width="600px" height="400px" @mousedown="startDrawing" @mousemove="draw" @mouseup="stopDrawing"></canvas>
  </div>
</template>

<script>
export default {
  data() {
    return {
      drawing: false,
      context: null,
      startX: 0,
      startY: 0,
      endX: 0,
      endY: 0
    };
  },
  mounted() {
    this.initializeCanvas();
  },
  methods: {
    initializeCanvas() {
      this.context = this.$refs.canvas.getContext('2d');
      this.context.strokeStyle = 'red';
      this.context.lineWidth = 2;
      this.context.strokeRect(300, 150, 10, 100);
    },
    startDrawing(event) {
      this.drawing = true;
      let rect = this.$refs.canvas.getBoundingClientRect()
      this.startX = event.clientX - rect.left;
      this.startY = event.clientY - rect.top;
    },
    draw(event) {
      if (!this.drawing) return;
      let rect = this.$refs.canvas.getBoundingClientRect()
      this.endX = event.clientX - rect.left;
      this.endY = event.clientY - rect.top;
      this.clearCanvas();
      this.drawLineArrow(this.context, this.startX, this.startY, this.endX, this.endY);
    },
    stopDrawing() {
      this.drawing = false;
      this.clearCanvas();
      this.startX = 0
      this.startY = 0
      this.endX = 0
      this.endY = 0
    },
    clearCanvas() {
      this.context.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height);

    },
    drawArrowLine(startX, startY, endX, endY) {
      this.context.beginPath();
      this.context.moveTo(startX, startY);
      this.context.lineTo(endX, endY);

      // 计算箭头的角度
      const angle = Math.atan2(endY - startY, endX - startX);

      // 绘制箭头部分
      const arrowSize = 10;
      this.context.lineTo(endX - arrowSize * Math.cos(angle - Math.PI / 6), endY - arrowSize * Math.sin(angle - Math.PI / 6));
      this.context.moveTo(endX, endY);
      this.context.lineTo(endX - arrowSize * Math.cos(angle + Math.PI / 6), endY - arrowSize * Math.sin(angle + Math.PI / 6));

      this.context.stroke();
    },
    /**
 * 
 * @param {*canvas context 对象} ctx 
 * @param {*起点横坐标} fromX 
 * @param {*起点纵坐标} fromY 
 * @param {*终点横坐标} toX 
 * @param {*终点纵坐标} toY 
 * 以下注释以终点在坐标第一象限内,且方向为右上方
 */
    drawLineArrow(ctx, fromX, fromY, toX, toY) {
      var headlen = 0.2 * 1.41 * Math.sqrt((fromX - toX) * (fromX - toX) + (fromY - toY) * (fromY - toY));//箭头头部长度
      headlen = headlen > 40 ? 40 : headlen;//40是箭头头部最大值
      var theta = 30;//自定义箭头线与直线的夹角
      var arrowX, arrowY;//箭头线终点坐标
      // 计算各角度和对应的箭头终点坐标
      var angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI;
      var angle1 = (angle + theta) * Math.PI / 180;
      var angle2 = (angle - theta) * Math.PI / 180;
      var topX = headlen * Math.cos(angle1);
      var topY = headlen * Math.sin(angle1);
      var botX = headlen * Math.cos(angle2);
      var botY = headlen * Math.sin(angle2);
      var toLeft = fromX > toX;
      var toUp = fromY > toY;

      //箭头最上点
      arrowX = toX + topX;
      arrowY = toY + topY;
      //箭头下拐点
      var arrowX1 = toX + botX;
      var arrowY1 = toY + botY;
      //箭头上拐点
      var arrowX2 = toUp ? arrowX + 0.25 * Math.abs(arrowX1 - arrowX) : arrowX - 0.25 * Math.abs(arrowX1 - arrowX);
      var arrowY2 = toLeft ? arrowY - 0.25 * Math.abs(arrowY1 - arrowY) : arrowY + 0.25 * Math.abs(arrowY1 - arrowY);
      //箭头最下点 
      var arrowX3 = toUp ? arrowX + 0.75 * Math.abs(arrowX1 - arrowX) : arrowX - 0.75 * Math.abs(arrowX1 - arrowX);
      var arrowY3 = toLeft ? arrowY - 0.75 * Math.abs(arrowY1 - arrowY) : arrowY + 0.75 * Math.abs(arrowY1 - arrowY);

      ctx.beginPath();
      //起点-起点,闭合
      ctx.moveTo(fromX, fromY);
      ctx.lineTo(arrowX2, arrowY2);
      ctx.lineTo(arrowX, arrowY);
      ctx.lineTo(toX, toY);

      ctx.lineTo(arrowX1, arrowY1);
      ctx.lineTo(arrowX3, arrowY3);
      ctx.lineTo(fromX, fromY);
      ctx.closePath();
      ctx.strokeStyle = "#FB8978";
      ctx.fillStyle = "rgba(255,197,179,0.3)";
      ctx.fill();
      ctx.stroke();

    }
  }
};
</script>

<style scoped>
/* 可以添加一些样式 */
.canvas {
  /* width: 800px;
  height: 500px; */
  background: #ccc;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/768457.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis持久化的三种方式(RDB、AOF和混合)

Redis持久化的三种方式(RDB、AOF和混合) 目录 Redis持久化的三种方式(RDB、AOF和混合)介绍RDB示例1.配置文件2.触发 RDB 快照保存3.验证 AOF示例1.配置文件2.校验 混合型持久化存储配置文件 介绍 Redis数据主要存储与内存中&#xff0c;因此如果服务器意外重启、宕机、崩溃&am…

elementui中@click短时间内多次触发,@click重复点击,做不允许重复点击处理

click快速点击&#xff0c;发生多次触发 2.代码示例&#xff1a; //html<el-button :loading"submitLoading" type"primary" click"submitForm">确 定</el-button>data() {return {submitLoading:false,}}//方法/** 提交按钮 */sub…

页面替换菜单栏图标

图标素材库&#xff1a;https://www.iconfont.cn/?spma313x.collections_index.i3.2.51703a81hOhc8B 1、找到自己喜欢的图标下载svg 2、添加到icons中 3、在components中创建对应的vue页面添加对应图标svg中代码 4、在router中引入 5、在对应的菜单下使用图标

复旦大学:一个小技巧探测大模型的知识边界,有效消除幻觉

孔子说“知之为知之&#xff0c;不知为不知&#xff0c;是知也”&#xff0c;目前的大模型非常缺乏这个能力。虽然大模型拥有丰富的知识&#xff0c;但它仍然缺乏对自己知识储备的正确判断。近年来LLMs虽然展现了强大的能力&#xff0c;但它们偶尔产生的内容捏造&#xff0c;即…

基于改进YOLOv5s的跌倒行为检测 | 引入SKAttention注意机制 + 引入空间金字塔池化结构SPPFCSPC + 结合ASFF自适应空间融合

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。为了实现电厂人员跌倒行为的实时检测&#xff0c;防止跌倒昏迷而无法及时发现并救援的事件发生&#xff0c;针对跌倒行为检测实时性以及特征提取能力不足的问题&#xff0c;提出了一种改进YOLOv5s的跌倒行为检测算法网络&a…

MySQL期末答辩—仓库管理系统

仓库管理系统&#xff1a;仓库管理系统是一种基于互联网对实际仓库的管理平台&#xff0c;旨在提供一个方便、快捷、安全的存取货物和查询商品信息平台。该系统通过在线用户登录查询&#xff0c;可以线上操作线下具体出/入库操作、查询仓库商品信息、提高仓库运作效率&#xff…

一文包学会ElasticSearch的大部分应用场合

ElasticSearch 官网下载地址&#xff1a;Download Elasticsearch | Elastic 历史版本下载地址1&#xff1a;Index of elasticsearch-local/7.6.1 历史版本下载地址2&#xff1a;Past Releases of Elastic Stack Software | Elastic ElasticSearch的安装(windows) 安装前所…

1000T的文件怎么能快速从南京传到北京?最佳方案你肯定想不到

今天刷面试题看到一个有意思的面试题&#xff0c; 1000T的文件怎么能以最快速度从南京传到北京&#xff1f; 网络传输 首先我们考虑通过网络传输&#xff0c;需要多长时间。 我特地咨询了在运营商工作的同学&#xff0c;目前带宽&#xff1a; 家庭宽带下行最大1Gbps&#…

双指针系列第 8 篇:盛水最多的容器。几句话讲明白!

Leetcode 题目链接 思路 取首尾双指针和水量如下所示&#xff0c;设高度函数为 h ( i ) h(i) h(i)&#xff0c;在下图中 h ( l ) < h ( r ) h(l) < h(r) h(l)<h(r)。 观察以 l l l 为左边界所能构成的其他水量&#xff0c;与矮的右边界搭配结果如下。 与高的…

每日两题 / 20. 有效的括号 155. 最小栈(LeetCode热题100)

20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; 遇到左括号入栈 遇到右括号判断栈顶是否为匹配的左括号 最后判断栈是否为空 func isValid(s string) bool {var stk []runefor _, value : range s {if value ( || value { || value [ {stk append(stk, value)}…

计算机操作系统部分选填及大题整理

并发和&#xff08; 共享 &#xff09; 是操作系统的两个最基本的特征,&#xff08; 虚拟 &#xff09;和&#xff08; 异步 &#xff09; 是操作系统的重要特征&#xff0c;并发执行的程序失去可再现性现代操作系统的两个基本特征是&#xff08;程序的并发执行&#xff09;和资…

Docker 部署 Minio 对象存储服务器

文章目录 Github官网文档简介dockerdocker-compose.ymlmc 客户端mc 基础命令Golang 示例创建 test 账号密钥文件上传示例 Github https://github.com/minio/minio 官网 https://min.io/https://www.minio.org.cn/ 文档 https://www.minio.org.cn/docs/minio/kubernetes/up…

1.4 ROS2集成开发环境搭建

1.4.1 安装VSCode VSCode全称Visual Studio Code&#xff0c;是微软推出的一款轻量级代码编辑器&#xff0c;免费、开源而且功能强大。它支持几乎所有主流的程序语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比Diff、GIT 等特性&#xff0c;支持插件…

上位机第二弹

之前写的代码用上了 现在想想 &#xff0c;北向一侧还挺难搞&#xff0c;设计很巧妙

10 Posix API与网络协议栈

POSIX概念 POSIX是由IEEE指定的一系列标准,用于澄清和统一Unix-y操作系统提供的应用程序编程接口(以及辅助问题,如命令行shell实用程序),当您编写程序以依赖POSIX标准时,您可以非常肯定能够轻松地将它们移植到大量的Unix衍生产品系列中(包括Linux,但不限于此!)。 如…

使用pyinstaller 如何打包python项目

参考&#xff1a;【python项目正确打包方法-哔哩哔哩】 https://b23.tv/EDB6zbG Pyinstaller 详解多种打包过程(去坑,填坑)。_pyinstaller -f -w-CSDN博客 1.打开命令提示符&#xff1a; 找到python项目所在位置&#xff0c;输入cmd即可 2. 安装pipenv: 在命令提示符&#…

【Linux】多线程(一万六千字)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 线程的概念 线程的理解(Linux系统为例) 在Linux系统里如何保证让正文部分的代码可以并发的去跑呢&#xff1f; 为什么要有多进程呢&#xff1f; 为…

CVD-Risk-Prevent 个性化心血管健康推荐系统:基于医学指南的规则框架与 LLM 的结合

CVD-Risk-Prevent 个性化心血管健康推荐系统&#xff1a;基于医学指南的规则框架与 LLM 的结合 提出背景推荐算法的选择选择疑问健康指标管理心血管风险因素目标设定实现目标的计划推荐的多维性 算法关键点&#xff1a;如何将心血管健康指标转换为多维推荐&#xff1f;确定风险…

antfu/ni 在 Windows 下的安装

问题 全局安装 ni 之后&#xff0c;第一次使用会有这个问题 解决 在 powershell 中输入 Remove-Item Alias:ni -Force -ErrorAction Ignore之后再次运行 ni Windows 11 下的 Powershell 环境配置 可以参考 https://github.com/antfu-collective/ni?tabreadme-ov-file#how …

【操作系统】进程管理——调度基础(个人笔记)

学习日期&#xff1a;2024.7.3 内容摘要&#xff1a;调度的概念、层次&#xff0c;进程调度的时机&#xff0c;调度器和闲逛进程&#xff0c;调度算法的评价指标 调度的基本概念 有一堆任务需要处理&#xff0c;但由于资源有限&#xff0c;有的事情不能同时处理&#xff0c;这…