Canvas进阶篇:鼠标交互动画

发布于:2025-05-22 ⋅ 阅读:(16) ⋅ 点赞:(0)

前言

在上一篇文章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 中处理鼠标点击和拖动事件的方法,对于文章中错误的地方或者有任何问题,欢迎在评论区留言分享!


网站公告

今日签到

点亮在社区的每一天
去签到