当前位置: 首页 > article >正文

Canvas进阶篇:鼠标交互动画

Canvas进阶篇:鼠标交互动画

  • 前言
  • 获取鼠标坐标
  • 鼠标事件
    • 点击事件监听
      • 代码示例
      • 效果预览
    • 拖动事件监听
      • 代码示例
      • 效果预览
  • 结语

前言

在上一篇文章Canvas进阶篇:基本动画详解 中,我们讲述了在Canvas中实现动画的基本步骤和动画的绘制方法。本文将进一步讲述如何通过鼠标事件增加动画和用户的交互,包括捕获鼠标的点击和拖动事件,获取鼠标在 Canvas 中坐标等。

获取鼠标坐标

在进行鼠标交互时,最主要的是要获取鼠标在Canvas中画布中的坐标。通常我们获取到的鼠标坐标都是相对于浏览器窗口的;如果想要获取相对于 Canvas 画布的坐标,就需要进行坐标转换,可以通过以下方式实现:

function getCanvasCoordinates(event) {const rect = canvas.getBoundingClientRect();const x = event.clientX - rect.left;const y = event.clientY - rect.top;return { x, y };
}

上述代码中,canvas.getBoundingClientRect()方法返回 Canvas 在浏览器窗口中的位置和尺寸信息,通过用鼠标相对于窗口的坐标减去 Canvas 左上角相对于窗口的坐标,就得到了鼠标在 Canvas 中的坐标。

鼠标事件

鼠标事件一共分为4类:鼠标点击事件click、鼠标按下事件mousedown、鼠标移动事件mousemove和鼠标松开事件mouseup

点击事件监听

利用点击事件,我们可以在鼠标点击的位置绘制各种图形,比如圆形等,示例代码如下:

代码示例

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>鼠标点击画圆</title><style>#canvas {border: 1px solid #000;}</style></head><body><canvas id="canvas" width="600" height="600"></canvas><script>const canvas = document.getElementById('canvas');const ctx = canvas.getContext('2d');function getCanvasCoordinates(event) {const rect = canvas.getBoundingClientRect();const x = event.clientX - rect.left;const y = event.clientY - rect.top;return { x, y };}function handleClick(event) {const {x,y} = getCanvasCoordinates(event);ctx.beginPath();ctx.arc(x, y, 20, 0, 2 * Math.PI);ctx.fillStyle = 'red';ctx.fill();}// 绑定鼠标点击事件canvas.addEventListener('click', handleClick);</script></body>
</html>

效果预览

鼠标点击画圆

拖动事件监听

实现拖动元素的功能,需要结合mousedownmousemovemouseup三个事件,我们以拖动一个矩形为例:

代码示例

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>鼠标拖动矩形</title><style>#canvas {border: 1px solid #000;}</style></head><body><canvas id="canvas" width="600" height="600"></canvas><script>const canvas = document.getElementById('canvas');const ctx = canvas.getContext('2d');function getCanvasCoordinates(event) {const rect = canvas.getBoundingClientRect();const x = event.clientX - rect.left;const y = event.clientY - rect.top;return {x,y};}// 矩形数组let rectangles = [];// 拖拽状态let isDragging = false;let startX, startY;let offsetX, offsetY;let draggedRect = null;function handleMouseDown(event) {const {x,y} = getCanvasCoordinates(event);for (const rect of rectangles) {if (x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height) {isDragging = true;draggedRect = rect;startX = x;startY = y;offsetX = x - rect.x;offsetY = y - rect.y;break;}}}function handleMouseMove(event) {if (isDragging) {const {x,y} = getCanvasCoordinates(event);if (draggedRect) {draggedRect.x = x - offsetX;draggedRect.y = y - offsetY;drawCanvas();}}}function handleMouseUp() {isDragging = false;draggedRect = null;}function drawCanvas() {ctx.clearRect(0, 0, canvas.width, canvas.height);for (const rect of rectangles) {ctx.beginPath();ctx.rect(rect.x, rect.y, rect.width, rect.height);ctx.fillStyle = 'blue';ctx.fill();}}// 绘制矩形function addRectangle() {const rect = {x: Math.random() * (canvas.width - 100),y: Math.random() * (canvas.height - 100),width: 80 + Math.random() * 40,height: 60 + Math.random() * 40,color: `hsl(${Math.random() * 360}, 70%, 60%)`};rectangles.push(rect);drawCanvas();}// 绑定鼠标按下事件,用于拖动起始canvas.addEventListener('mousedown', handleMouseDown);// 绑定鼠标移动事件,用于拖动过程canvas.addEventListener('mousemove', handleMouseMove);// 绑定鼠标松开事件,用于拖动结束canvas.addEventListener('mouseup', handleMouseUp);addRectangle();</script></body>
</html>

效果预览

鼠标拖动矩形

结语

本文主要介绍了在 Canvas 中处理鼠标点击和拖动事件的方法,对于文章中错误的地方或者有任何问题,欢迎在评论区留言分享!

http://www.lryc.cn/news/2383417.html

相关文章:

  • Mac下载bilibili视频
  • Unity editor文件数UI(支持勾选框)
  • 【Node.js】Web开发框架
  • 使用Vite创建一个动态网页的前端项目
  • 系统架构设计师案例分析题——web篇
  • MySQL--day5--多表查询
  • 【Redis】AOF日志的三种写回机制
  • leetcode hot100刷题日记——7.最大子数组和
  • 基于Spring Boot和Vue的在线考试系统架构设计与实现(源码+论文+部署讲解等)
  • MySQL Workbench 工具导出与导入数据库:实用指南
  • Android 绘制折线图
  • 自建srs实时视频服务器支持RTMP推流和拉流
  • ubuntu22.04 卸载ESP-IDF
  • Spring IOCDI————(2)
  • 80. Java 枚举类 - 使用枚举实现单例模式
  • 融云 uni-app IMKit 上线,1 天集成,多端畅行
  • Java中的集合详解
  • 利用 Java 爬虫根据关键词获取某手商品列表
  • Axure项目实战:智慧运输平台后台管理端-订单管理2(多级交互)
  • 篇章五 项目创建
  • Ntfs!ATTRIBUTE_RECORD_HEADER结构$INDEX_ROOT=0x90的一个例子
  • AGI大模型(30):LangChain链的基本使用
  • 代码随想录算法训练营第六十六天| 图论11—卡码网97. 小明逛公园,127. 骑士的攻击
  • [创业之路-364]:企业战略管理案例分析-5-战略制定-宇树科技的使命、愿景、价值观的演变过程
  • React--函数组件和类组件
  • Flask 路由装饰器:从 URL 到视图函数的优雅映射
  • DDoS防护实战——从基础配置到高防IP部署
  • aws平台s3存储桶夸域问题处理
  • HOT100(二叉树)
  • 【vue-text-highlight】在vue2的使用教程