如何使用translate方法实现可拖拽Canvas?上下拖拽失效求助
问题描述
想要实现类似Google Maps的游戏地图拖拽效果,但当前代码仅能左右拖拽,无法上下拖拽,需要简单易懂的解决方案。
原尝试代码
JavaScript
const canvas = document.querySelector('canvas'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; const ctx = canvas.getContext('2d'); const drawRects = () => { ctx.fillStyle = 'red'; ctx.fillRect(0, 0, 1000, 1000); ctx.fillStyle = 'aqua'; ctx.fillRect(1000, 1000, 1000, 1000); ctx.fillStyle = 'green'; ctx.fillRect(0, 1000, 1000, 1000); ctx.fillStyle = 'magenta'; ctx.fillRect(1000, 0, 1000, 1000); } const mouse = { isDown: false, isUp: false, isPressed: false, x: 0, y: 0 } const pos = { x: 0, y: 0 } function tick() { ctx.setTransform(1, 0, 0, 1, 0, 0); canvas.width += 0; if(mouse.isPressed){ ctx.translate(mouse.x - pos.x, mouse.y - pos.y) } drawRects() requestAnimationFrame(tick) } canvas.addEventListener('mousedown', e => { pos.x = e.offsetX; pos.y = e.offsetY; mouse.isDown = true; mouse.isUp = false; mouse.isPressed = true; }) canvas.addEventListener('mousemove', e => { if(!mouse.isDown) return; mouse.x = e.offsetX; mouse.y = e.offsetY; }) canvas.addEventListener('mouseup', e => { mouse.isDown = false; mouse.isUp = true; }) tick()
CSS
body{ margin: 0; }
HTML
<canvas></canvas>
解决方案
问题根源
- 错误的清屏方式:使用
canvas.width += 0会重置画布的所有状态(包括Y轴相关的变换),直接导致上下拖拽失效; - 拖拽逻辑缺陷:没有累积画布的偏移量,且鼠标松开后未重置
mouse.isPressed,导致拖拽逻辑混乱。
修改后的代码
const canvas = document.querySelector('canvas'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; const ctx = canvas.getContext('2d'); // 记录画布的累积偏移量 const offset = { x: 0, y: 0 }; // 记录鼠标按下时的初始位置 const startMouse = { x: 0, y: 0 }; const drawRects = () => { ctx.fillStyle = 'red'; ctx.fillRect(0, 0, 1000, 1000); ctx.fillStyle = 'aqua'; ctx.fillRect(1000, 1000, 1000, 1000); ctx.fillStyle = 'green'; ctx.fillRect(0, 1000, 1000, 1000); ctx.fillStyle = 'magenta'; ctx.fillRect(1000, 0, 1000, 1000); } function tick() { // 重置变换并正确清屏 ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); // 应用累积的偏移量 ctx.translate(offset.x, offset.y); drawRects(); requestAnimationFrame(tick); } canvas.addEventListener('mousedown', e => { // 记录鼠标按下时的位置 startMouse.x = e.offsetX; startMouse.y = e.offsetY; }); canvas.addEventListener('mousemove', e => { if (!e.buttons) return; // 仅当鼠标左键按下时响应 // 计算鼠标移动差值,更新画布偏移 offset.x += e.offsetX - startMouse.x; offset.y += e.offsetY - startMouse.y; // 更新鼠标初始位置,确保后续移动计算准确 startMouse.x = e.offsetX; startMouse.y = e.offsetY; }); tick();
关键修改点
- 用
ctx.clearRect(0, 0, canvas.width, canvas.height)替代canvas.width += 0,正确清屏且不破坏画布状态; - 新增
offset对象记录画布的累积偏移量,实现连贯的拖拽效果; - 使用
e.buttons判断鼠标按下状态,简化状态管理; - 鼠标移动时实时更新累积偏移量,确保XY轴拖拽逻辑一致。
内容的提问来源于stack exchange,提问作者user20478727
相关产品推荐
相关产品推荐

