如何在canvas内拖拽已绘制的圆形,基于requestAnimationFrame实现
功能实现解决方案
新增全局状态变量
首先在全局作用域定义以下变量,用于存储交互状态:
// 圆形基础配置 const circleRadius = 40 // 圆形初始位置(可根据芝士图片实际展示位置调整x、y数值,放在芝士上方即可) let circleX = 200 let circleY = 150 // 拖拽状态标记 let isDragging = false // 老鼠图片状态标记 let isMouseCelebrate = false // 鼠标按下时与圆形中心的偏移量,避免拖拽时圆形出现跳变 let dragOffsetX = 0 let dragOffsetY = 0
新增/修改事件监听逻辑
保留原有mousemove监听的基础上,新增鼠标按下、松开事件:
// 新增鼠标按下事件,判断点击位置是否在圆形范围内 canvas.addEventListener("mousedown", (e) => { const mouseX = e.clientX - canvasPos.x const mouseY = e.clientY - canvasPos.y // 计算鼠标到圆形中心的距离,判断是否触发拖拽 const distance = Math.sqrt(Math.pow(mouseX - circleX, 2) + Math.pow(mouseY - circleY, 2)) if (distance < circleRadius) { isDragging = true dragOffsetX = mouseX - circleX dragOffsetY = mouseY - circleY } }, false) // 新增鼠标松开事件,结束拖拽并切换老鼠图片状态 canvas.addEventListener("mouseup", () => { if (isDragging) { isDragging = false isMouseCelebrate = true } }, false) // 修改原有mousemove事件逻辑,拖拽时同步更新圆形位置 function setMousePosition(e) { const currentMouseX = e.clientX - canvasPos.x const currentMouseY = e.clientY - canvasPos.y if (isDragging) { circleX = currentMouseX - dragOffsetX circleY = currentMouseY - dragOffsetY } }
修改update渲染函数
调整圆形绘制逻辑和老鼠图片加载逻辑:
function update() { context.clearRect(0,0,canvas.width, canvas.height) drawText() loadCheese() // 根据状态加载对应老鼠图片 if (isMouseCelebrate) { // 替换为你自己实现的庆祝状态老鼠图片绘制方法即可 loadCelebrateMouse() } else { loadMouse() } drawLine() context.beginPath() // 用动态更新的circleX、circleY绘制圆形 context.arc(circleX, circleY, circleRadius, 0, 2 * Math.PI, true) context.fillStyle = "#FF6A6A" context.fill() context.stroke() requestAnimationFrame(update) }
实现说明
- 使用两点距离公式判断鼠标是否在圆形范围内,比单纯判断坐标大小的准确率更高,不会出现边角误判的问题
- 拖拽偏移量设置解决了鼠标点击圆形非中心位置时,圆形突然跳转到鼠标中心的不良体验
- 所有渲染逻辑都放在requestAnimationFrame驱动的update函数中,保证状态和视图同步的同时性能最优
内容的提问来源于stack exchange,提问作者sidereal
相关产品推荐
相关产品推荐

