Canvas鼠标画线
鼠标按下开始画线,鼠标移动根据鼠标的轨迹去画,鼠标抬起停止画线
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Canvas Drawing</title><style>canvas {border: 1px solid #000;}</style>
</head><body><canvas id="myCanvas" width="500" height="500"></canvas><script>document.addEventListener('DOMContentLoaded', function () {const canvas = document.getElementById('myCanvas')const ctx = canvas.getContext('2d')let isDrawing = falsefunction startDrawing (e) {isDrawing = truedraw(e)}function stopDrawing () {isDrawing = falsectx.beginPath() // Reset the path for the next draw}function draw (e) {if (!isDrawing) returnctx.lineWidth = 5ctx.lineCap = 'round'ctx.strokeStyle = '#000'ctx.lineTo(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop)ctx.stroke()ctx.beginPath()ctx.moveTo(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop)}canvas.addEventListener('mousedown', startDrawing)canvas.addEventListener('mousemove', draw)canvas.addEventListener('mouseup', stopDrawing)canvas.addEventListener('mouseout', stopDrawing)});</script>
</body></html>
效果图

和上面效果相同,只是轨迹线换成了直线(鼠标移动始终显示两点直线,只能绘制有一条线)
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Canvas Drawing</title><style>canvas {border: 1px solid #000;}</style>
</head><body><canvas id="myCanvas" width="500" height="500"></canvas><script>document.addEventListener('DOMContentLoaded', function () {const canvas = document.getElementById('myCanvas')const ctx = canvas.getContext('2d')let isDrawing = falselet startX, startYfunction startDrawing (e) {isDrawing = truestartX = e.clientX - canvas.offsetLeftstartY = e.clientY - canvas.offsetTop}function drawLine (e) {if (!isDrawing) returnconst endX = e.clientX - canvas.offsetLeftconst endY = e.clientY - canvas.offsetTopctx.clearRect(0, 0, canvas.width, canvas.height) // Clear the canvasctx.lineWidth = 5ctx.lineCap = 'round'ctx.strokeStyle = '#000'ctx.beginPath()ctx.moveTo(startX, startY)ctx.lineTo(endX, endY)ctx.stroke()}function stopDrawing () {isDrawing = false}canvas.addEventListener('mousedown', startDrawing)canvas.addEventListener('mousemove', drawLine)canvas.addEventListener('mouseup', stopDrawing)canvas.addEventListener('mouseout', stopDrawing)});</script>
</body></html>
效果图

效果图和上面相同(可以画多条直线,点击确定按钮会保留最后画的一条线)
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Canvas Drawing</title><style>canvas {border: 1px solid #000;margin-bottom: 20px;}button {display: block;margin-top: 10px;}</style>
</head><body><canvas id="myCanvas" width="500" height="500"></canvas><button id="confirmButton">Confirm</button><script>document.addEventListener('DOMContentLoaded', function () {const canvas = document.getElementById('myCanvas')const ctx = canvas.getContext('2d')let lines = [] // 画线的数组let lines2 = [] // 点击确定后存放的按钮let num = 0let isDrawing = falselet startPoint = {}let endPoint = {}function startDrawing (e) {isDrawing = truestartPoint = {x: e.clientX - canvas.offsetLeft,y: e.clientY - canvas.offsetTop}}function drawLine (e) {if (!isDrawing) returnendPoint = {x: e.clientX - canvas.offsetLeft,y: e.clientY - canvas.offsetTop}ctx.clearRect(0, 0, canvas.width, canvas.height) // Clear the canvasctx.lineWidth = 5ctx.lineCap = 'round'ctx.strokeStyle = '#000'lines.forEach(line => {ctx.beginPath()ctx.moveTo(line.start.x, line.start.y)ctx.lineTo(line.end.x, line.end.y)ctx.stroke()})ctx.beginPath()ctx.moveTo(startPoint.x, startPoint.y)ctx.lineTo(endPoint.x, endPoint.y)ctx.stroke()}function stopDrawing () {if (isDrawing) {isDrawing = falselines.push({ start: { ...startPoint }, end: { ...endPoint } })}}function confirmLines () {lines2.push(lines[lines.length - 1])lines = [...lines2]ctx.clearRect(0, 0, canvas.width, canvas.height) // Clear the canvasif (lines2.length > 0) {lines2.forEach((item) => {const lastLine = itemctx.beginPath()ctx.moveTo(lastLine.start.x, lastLine.start.y)ctx.lineTo(lastLine.end.x, lastLine.end.y)ctx.stroke()})}}canvas.addEventListener('mousedown', startDrawing)canvas.addEventListener('mousemove', drawLine)canvas.addEventListener('mouseup', stopDrawing)canvas.addEventListener('mouseout', stopDrawing)const confirmButton = document.getElementById('confirmButton')confirmButton.addEventListener('click', confirmLines)});</script>
</body></html>
相关文章:
Canvas鼠标画线
鼠标按下开始画线,鼠标移动根据鼠标的轨迹去画,鼠标抬起停止画线 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…...
Docker 安装部署 Sentinel Dashboard
1、下载 jar 包 官方 jar 包下载地址:https://github.com/alibaba/Sentinel/releases 或者点击 链接 直接跳转到下载页 进入链接下载你需要的版本 下载完毕(我这里统一放在一个sentinel目录内) 2、编写 Dockerfile 文件(这里我不…...
第21章网络通信
Internet 提供了大量有用的信息,很少有人能在接触过Internet后拒绝它的诱惑。计算机网络实现了多台计算机间的互联,使得它们彼此之间能够进行数据交流。网络应用程序就是在已连接的不同计算机上运行的程序,这些程序借助于网络协议,…...
一、运行时数据区域
根据 《Java 虚拟机规范》的规定,Java 虚拟机所管理的内存将会包括以下截个运行时数据区域,如图所示。 1、程序计数器 程序计数器是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器。在 Java 虚拟机的概念模型里&#x…...
OCR原理解析
目录 1.概述 2.应用场景 3.发展历史 4.基于传统算法的OCR技术原理 4.1 图像预处理 4.1.1 灰度化 4.1.2 二值化 4.1.3 去噪 4.1.4 倾斜检测与校正 4.1.4.2 轮廓矫正 4.1.5 透视矫正 4.2 版面分析 4.2.1 连通域检测文本 4.2.2 MSER检测文本 4.3 字符切割 4.3.1 连…...
使用com组件编辑word
一个普通的窗体应用,6个button using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; u…...
国产Euler(欧拉)系统安装docker
国产的真™难用呀 生态又差还不开源 血泪经验 解压Docker安装包。 tar zxf docker-19.03.10.tgz 将解压后目录中的文件移动到“/usr/bin”下。 cp docker/* /usr/bin配置docker.service文件。 编辑docker.service文件。 vim /usr/lib/systemd/system/docker.service添加以…...
Linux 进程控制
文章目录 进程创建进程终止进程结果wait函数waitpid函数status参数 进程替换进程替换原理进程替换函数 补充/拓展 进程创建 fork函数 #include <unistd.h>pid_t fork(void);函数返回值: 在父进程中,fork函数返回子进程的进程ID(PID&…...
[ Linux Audio 篇 ] 音频开发入门基础知识
在短视频兴起的背景下,音视频开发越来越受到重视。接下来将为大家介绍音频开发者入门知识,帮助读者快速了解这个领域。 轻柔的音乐、程序员有节奏感的键盘声、嗡嗡的发动机、刺耳的手提钻……这些声音是如何产生的呢?又是如何传到我们耳中的…...
关于高校电子邮件系统开通双因素认证的经验分享-以清华大学为例
清华大学信息化技术中心 马云龙 作者简介: 马云龙,男,清华大学信息化技术中心高级工程师;Coremail管理员社区大咖嘉宾 深耕高校计算机网络/信息化/网络安全岗位20年,对大规模计算机网络及信息系统规划,开发/建设,运维有深刻体会。 目前,越来越多的高校/企业/政府机关…...
「Swift」类淘宝商品瀑布流展示
前言:需要做一个类似于淘宝商品页面的瀑布流展示 结构分析: ps:图片来源 思路分析: 该瀑布流主要还是基于UICollectionView进行展示,只是在cell展示的UICollectionViewFlowLayout需要进行相应调整和自定义ÿ…...
道可云会展元宇宙平台全新升级,打造3D沉浸式展会新模式
随着VR虚拟现实、人工智能、虚拟数字人等元宇宙技术的快速发展,各个行业正试图通过元宇宙技术寻求新的发展突破口,会展行业也不例外。会展作为经贸领域的重要产业形态,越来越多的企业和组织开始寻求通过元宇宙技术为展会赋能,以满…...
Ant Design Pro初始化报错
今天按照官网步骤初始化项目,第一次报错 fatal: unable to access https://github.com/ant-design/ant-design-pro/: SSL certificate problem: unable to get local issuer certificate 致命:无法访问https://github.com/ant-design/ant-design-pro/&…...
第16届中国R会议暨2023X-AGI大会开幕,和鲸科技分享ModelOps在数据科学平台中的实践与应用
11月25日,第 16 届中国 R 会议暨 2023 X-AGI 大会在在中国人民大学逸夫会堂拉开帷幕,本次会议由中国人民大学统计学院、中国人民大学应用统计科学研究中心、统计之都、原灵科技和中国商业统计学会人工智能分会(筹)主办,…...
❀My学习Linux命令小记录(12)❀
目录 ❀My学习Linux命令小记录(12)❀ 46.arp指令 47.tcpdump指令 48.chmod指令 49.chown指令 50.bash调用脚本指令 shell介绍 shell脚本的组成部分 脚本执行方式 检查脚本语法 bash之变量 变量的种类:根据生效的范围不同来区分 …...
MySQL学习day05
DCL(Data Control Language)数据控制语言学习 作用:用来创建数据库用户、控制数据库的访问权限 1)查询用户: use mysql; select * from user; 2)创建用户: create user 用户名主机名 identifi…...
JAVA面试题7
1.Java中的ClassLoader是什么? 它有什么作用? 答案:ClassLoader是一种加载Java类文件的机制,可以从不同的来源加载类文件,如本地文件系统、网络等。ClassLoader可以帮助实现模块化开发和动态加载类等功能。 2.什么是J…...
好用免费的AI换脸5个工具
在当今社会的发展中,人工智能(Artificial Intelligence, AI)扮演着关键的角色,其应用领域不断扩展。作为AI的一个分支,换脸技术近年来备受欢迎。这项技术使得将一个人的面部特征迁移到另一个人的照片或视频成为可能。除…...
【Linux】公网远程访问AMH服务器管理面板
目录 1. Linux 安装AMH 面板2. 本地访问AMH 面板3. Linux安装Cpolar4. 配置AMH面板公网地址5. 远程访问AMH面板6. 固定AMH面板公网地址 AMH 是一款基于 Linux 系统的服务器管理面板,它提供了一系列的功能,包括网站管理、FTP 管理、数据库管理、DNS 管理、…...
随笔-这都是命吗
我与鹏哥、小付有个小群,前几天,鹏哥在群里发了一个图,是他那个城市准备扶持的高新产业,有元宇宙、量子信息、生物制药、人工智能什么的。 先前的时候鹏哥给我说过,当地准备了六百多亩地,准备发展高新产业…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
Unity VR/MR开发-VR开发与传统3D开发的差异
视频讲解链接:【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...
