js 鼠标拖动canvas画布

功能点:

  • 鼠标拖拽canvas画布移动
  • 鼠标检测rect
  • 鼠标检测circle

代码

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>鼠标移动画布-事件检测</title><style>html,body {margin: 0;padding: 0;height: 100%;width: 100%;overflow: hidden;}</style></head><body><canvas id="canvas"></canvas><script>const canvas = document.getElementById('canvas');const { clientWidth: width, clientHeight: height } = document.body;canvas.width = width;canvas.height = height;const ctx = canvas.getContext('2d');// 储累积的偏移量let totalOffsetX = 0;let totalOffsetY = 0;// 缩放系数let scale = 1;// 图形数据const shapes = [{type: 'rect',x: 100,y: 100,width: 20,height: 20,strokeStyle: '#000',fillStyle: '#f00',},{type: 'circle',x: 200,y: 200,radius: 10,strokeStyle: '#000',fillStyle: '#0f0',},{type: 'polyline',points: [{ x: 200, y: 100 },{ x: 150, y: 100 },{ x: 200, y: 150 },],strokeStyle: '#000',fillStyle: '#00f',},];function render(offsetX, offsetY) {// 绘制时需要使用beginPath,否则无法使用clearRect清空画布ctx.clearRect(0, 0, width, height);ctx.fillStyle = '#999';ctx.fillRect(0, 0, width, height);ctx.fill();ctx.translate(totalOffsetX, totalOffsetY);ctx.scale(scale, scale);shapes.forEach((shape) => {const { type, x, y, width, height, radius, points } = shape;ctx.fillStyle = shape.fillStyle;ctx.beginPath();if (type === 'rect') {ctx.fillRect(x, y, width, height);} else if (type === 'circle') {ctx.arc(x, y, radius, 0, Math.PI * 2);} else if (type === 'polyline') {ctx.moveTo(points[0].x, points[0].y);points.slice(1).forEach((point) => {ctx.lineTo(point.x, point.y);});ctx.closePath();}ctx.fill();});ctx.resetTransform();}render();canvas.addEventListener('mousedown', onMouseDown);canvas.addEventListener('mousemove', onMouseMove);canvas.addEventListener('mouseup', onMouseUp);canvas.addEventListener('mouseleave', onMouseLeave);canvas.addEventListener('wheel', onWheel);let isMouseDown = false;let startX, startY;function onMouseDown(e) {canvas.style.cursor = 'grab';isMouseDown = true;startX = e.offsetX;startY = e.offsetY;}function onMouseMove(e) {isShapePoint(e);if (isMouseDown) {totalOffsetX += e.offsetX - startX;totalOffsetY += e.offsetY - startY;startX = e.offsetX;startY = e.offsetY;requestAnimationFrame(render);}}function onMouseUp(e) {isMouseDown = false;}function onMouseLeave(e) {isMouseDown = false;}function onWheel(e) {// 缩放,最大5倍,最小0.2倍if (e.deltaY === -100) {if (scale + 0.1 > 5) return;// 放大scale += 0.1;} else {if (scale - 0.1 <= 0.2) return;// 缩小scale -= 0.1;}requestAnimationFrame(render);}// 检测设备function isShapePoint(e) {const { offsetX, offsetY } = e;let check = false;shapes.forEach((shape) => {// 检测rectif (shape.type === 'rect') {const { type, x, y, width, height } = shape;const transformedX = (offsetX - totalOffsetX) / scale;const transformedY = (offsetY - totalOffsetY) / scale;if (transformedX >= x &&transformedX <= x + width &&transformedY >= y &&transformedY <= y + height) {check = true;}} else if (shape.type === 'circle') {// 检测圆形const { x, y, radius } = shape;const transformedX = (offsetX - totalOffsetX) / scale;const transformedY = (offsetY - totalOffsetY) / scale;const circleX = x;const circleY = y;// 计算光标与圆心的距离const distance = Math.sqrt((transformedX - circleX) ** 2 + (transformedY - circleY) ** 2);if (radius >= distance) {check = true;}} else if (shape.type === 'polyline') {const { points: polygon } = shape;let inside = false;const transformedX = (offsetX - totalOffsetX) / scale;const transformedY = (offsetY - totalOffsetY) / scale;for (let i = 0, j = polygon.length - 1;i < polygon.length;j = i++) {const xi = polygon[i].x,yi = polygon[i].y;const xj = polygon[j].x,yj = polygon[j].y;const intersect =yi > transformedY !== yj > transformedY &&transformedX <((xj - xi) * (transformedY - yi)) / (yj - yi) + xi;if (intersect) {inside = !inside;if (inside) {check = true;} else {check = false;}}}}});if (check) {canvas.style.cursor = 'move';} else {canvas.style.cursor = 'grab';}}</script></body>
</html>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL 干货 | SQL 半连接

大多数数据库开发人员和管理员都熟悉标准的内、外、左和右连接类型。虽然可以使用 ANSI SQL 编写这些连接类型&#xff0c;但还有一些连接类型是基于关系代数运算符的&#xff0c;在 SQL 中没有语法表示。今天我们将学习一种这样的连接类型&#xff1a;半连接&#xff08;Semi …

PyTorch 中 12 种张量操作详解

创作不易&#xff0c;还请各位同学三连点赞&#xff01;&#xff01;收藏&#xff01;&#xff01;转发&#xff01;&#xff01;&#xff01; 对于刚入门学习Python还找不到方向的小伙伴可以试试我的这份学习方法和籽料&#xff0c;免费自取&#xff01;&#xff01; PyTorc…

后台管理员登录实现--系统篇

我的小系统后台原来就有一个上传图片的功能还夹带个删除图片的功能&#xff0c;还嵌到了一个菜单里面。之前效果如下 那么现在为了加大安全力度&#xff0c;想增加一个登录页面。通过登录再到这个页面。看着貌似很简单&#xff0c;但是听我细细说来&#xff0c;要新增些什么东西…

机器学习——元学习(Meta-learning)

元学习&#xff08;Meta-learning&#xff09;&#xff1a;学习如何学习的机器学习 元学习&#xff08;Meta-learning&#xff09;&#xff0c;即“学习如何学习”&#xff0c;是机器学习领域中一个令人兴奋且极具潜力的研究方向。它的核心目标是让机器学习系统学会高效地学习…

海港[NOIP2016]

题目描述 小 K 是一个海港的海关工作人员&#xff0c;每天都有许多船只到达海港&#xff0c;船上通常有很多来自不同国家的乘客。 小 K 对这些到达海港的船只非常感兴趣&#xff0c;他按照时间记录下了到达海港的每一艘船只情况&#xff1b;对于第 i 艘到达的船&#xff0c;他…

C#第四讲:C#语言基本元素概览,初识类型、变量与方法,算法简介

一、构成C#语言的基本元素 1、标识符 允许将下划线用作初始字符(这是C编程语言的传统)。 允许在标识符中使用 Unicode 转义序列&#xff0c;以及允许“”字符作为前缀以使关键字能够用作标识符。 &#xff08;1&#xff09;命名方法 变量名&#xff1a;用驼峰法。&#xff…

【SQL实验】表的更新和简单查询

完整代码在文章末尾 在上次实验创建的educ数据库基础上&#xff0c;用SQL语句为student表、course表和sc表中添加以下记录 【SQL实验】数据库、表、模式的SQL语句操作_创建一个名为educ数据库,要求如下: (下面三个表中属性的数据类型需要自己设计合适-CSDN博客在这篇博文中已经…

安全见闻---清风

注&#xff1a;本文章源于泷羽SEC&#xff0c;如有侵权请联系我&#xff0c;违规必删 学习请认准泷羽SEC学习视频:https://space.bilibili.com/350329294 安全见闻1 泷哥语录&#xff1a;安全领域什么都有&#xff0c;不要被表象所迷惑&#xff0c;无论技术也好还是其他方面…

YoloV9改进策略:主干网络改进|DeBiFormer,可变形双级路由注意力|全网首发

摘要 在目标检测领域,YoloV9以其高效和准确的性能而闻名。然而,为了进一步提升其检测能力,我们引入了DeBiFormer作为YoloV9的主干网络。这个主干网络的计算量比较大,不过,上篇双级路由注意力的论文受到很大的关注,所以我也将这篇论文中的主干网络用来改进YoloV9,卡多的…

[jeecg-boot] vue3 版本 nvm 下载node版本

安装pnpm 使用cnpm 进行下载依赖

JavaWeb 23.一文速通npm的配置和使用

目录 一、npm的介绍 二、npm的安装和配置 1.安装 &#xff1a; 2.配置依赖下载使用阿里镜像 3. 配置全局依赖下载后存储位置 4.升级npm版本 5.环境变量配置 三、npm常用命令 1.项目初始化 npm.init npm init -y 2.安装依赖文件 3. 升级依赖 4.卸载依赖 5.查看依赖 查看项目…

深入浅出 Vue3 nextTick

程序员节日快乐~ #1024程序员节 | 征文# nextTick 概念 当你在 Vue 的响应式数据模型中对数据进行修改时&#xff0c;这些变化并不会立即同步到 DOM 上_&#xff0c;而是会在当前的微任务队列&#xff08;microtask queue&#xff09;执行完毕后进行批量更新。这种机制被称为…

内网穿透:如何借助Cloudflare连接没有公网的电脑的远程桌面(RDP)

内网穿透&#xff1a;如何借助Cloudflare连接没有公网的电脑的远程桌面(RDP)-含详细原理配置说明介绍 前言 远程桌面协议(RDP, Remote Desktop Protocol)可用于远程桌面连接&#xff0c;Windows系统&#xff08;家庭版除外&#xff09;也是支持这种协议的&#xff0c;无需安装…

使用 NumPy 和 Matplotlib 实现交互式数据可视化

使用 NumPy 和 Matplotlib 实现交互式数据可视化 在数据分析中&#xff0c;交互式可视化可以更好地帮助我们探索和理解数据。虽然 Matplotlib 是静态绘图库&#xff0c;但结合一些技巧和 Matplotlib 的交互功能&#xff08;widgets、event handlers&#xff09;&#xff0c;我…

UE5里的TObjectPtr TSharedPtr TWeakPtr有什么区别

在 Unreal Engine&#xff08;UE&#xff09;编程中&#xff0c;TObjectPtr、TSharedPtr 和 TWeakPtr 都是 指针类型&#xff0c;但它们在生命周期管理和使用场景上有不同的特点。让我们详细分析这些指针的区别和用途。 TObjectPtr TObjectPtr 是 UE5 中引入的新智能指针类型…

水轮发电机油压自动化控制系统解决方案介绍

在现代水电工程中&#xff0c;水轮机组油压自动化控制系统&#xff0c;不仅直接关系到水轮发电机组的安全稳定运行&#xff0c;还影响着整个水电站的生产效率和经济效益。 一、系统概述 国科JSF油压自动控制系统&#xff0c;适用于水轮发电机组调速器油压及主阀&#xff08;蝶…

Dongle Sentinal在Jenkins下访问不了的问题

背景&#xff1a; 工作站部署的jenkins的脚本无法正常打包&#xff0c;定位后发现是本地获取不了license&#xff0c;但是使用usb over network的远程license都能获取并正常打包 分析&#xff1a; 获取不了license的原因是本地无法识别dongle。根据提供信息&#xff0c;之前…

SAP_SD模块-销售订单创建价格扩大10倍问题分析及后续订单价格批量更新问题处理

一、业务背景 我们公司的销售订单&#xff0c;是通过第三方销售管理平台创建好订单后&#xff0c;把表头和行项目数据&#xff0c;定时推送到SAP&#xff1b;SAP通过自定义表ZZT_ORDER_HEAD存放订单表头数据&#xff0c;通过ZZT_ORDER_DETAIL存放行项目数据&#xff1b;然后再用…

深入探讨 HTTP 请求方法:GET、POST、PUT、DELETE 的实用指南

文章目录 引言GET 方法POST 方法PUT 方法DELETE 方法小结适用场景与特点总结最佳实践 在 API 设计中的重要性 引言 HTTP 协议的背景&#xff1a;介绍 HTTP&#xff08;超文本传输协议&#xff09;作为互联网的基础协议&#xff0c;自 1991 年发布以来&#xff0c;成为客户端和…

探索AI人工智能机器学习:解锁未来科技的钥匙

作者简介&#xff1a;我是团团儿&#xff0c;是一名专注于云计算领域的专业创作者&#xff0c;感谢大家的关注 座右铭&#xff1a; 云端筑梦&#xff0c;数据为翼&#xff0c;探索无限可能&#xff0c;引领云计算新纪元 个人主页&#xff1a;团儿.-CSDN博客 前言&#xff1a;…