实现画布拖拽js
实现画布拖拽的基本思路
通过JavaScript监听鼠标事件(mousedown、mousemove、mouseup)来计算画布位移。核心是通过记录鼠标按下时的初始位置和移动时的偏移量,动态更新画布的transform样式或直接修改left/top值。
基础实现代码示例
<div id="canvas" style="width: 500px; height: 500px; background: #eee; position: absolute;"></div>
const canvas = document.getElementById('canvas');
let isDragging = false;
let startX, startY;
let offsetX = 0, offsetY = 0;
canvas.addEventListener('mousedown', (e) => {
isDragging = true;
startX = e.clientX - offsetX;
startY = e.clientY - offsetY;
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
offsetX = e.clientX - startX;
offsetY = e.clientY - startY;
canvas.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
});
document.addEventListener('mouseup', () => {
isDragging = false;
});
使用CSS Transform优化性能
推荐使用transform而非直接修改left/top,因为前者不会触发重排(reflow),性能更好。若需支持惯性滑动等高级效果,可结合requestAnimationFrame:
let lastX = 0, lastY = 0;
let velocityX = 0, velocityY = 0;
const friction = 0.95;
function animate() {
velocityX *= friction;
velocityY *= friction;
offsetX += velocityX;
offsetY += velocityY;
canvas.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
requestAnimationFrame(animate);
}
animate();
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
velocityX = e.movementX;
velocityY = e.movementY;
offsetX += e.movementX;
offsetY += e.movementY;
});
边界限制处理
防止画布被拖出可视区域,可在mousemove事件中添加边界检查:
const maxX = window.innerWidth - canvas.offsetWidth;
const maxY = window.innerHeight - canvas.offsetHeight;
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
offsetX = Math.min(maxX, Math.max(0, e.clientX - startX));
offsetY = Math.min(maxY, Math.max(0, e.clientY - startY));
canvas.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
});
触摸屏适配
添加touchstart、touchmove和touchend事件支持:
canvas.addEventListener('touchstart', (e) => {
isDragging = true;
const touch = e.touches[0];
startX = touch.clientX - offsetX;
startY = touch.clientY - offsetY;
e.preventDefault();
});
document.addEventListener('touchmove', (e) => {
if (!isDragging) return;
const touch = e.touches[0];
offsetX = touch.clientX - startX;
offsetY = touch.clientY - startY;
canvas.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
e.preventDefault();
});
使用第三方库简化
若项目复杂,可考虑使用现成库:
- Interact.js:支持拖拽、缩放和手势
- Hammer.js:专注于触摸手势处理
- Draggable:Shopify开源的拖拽库







