鼠标框选时矩形区域出现断层怎么办?
大家好,我在用canvas做鼠标框选功能时遇到个怪问题。当快速拖动鼠标画选区时,矩形边框会出现断断续续的缺口,特别是拖动速度越快断层越多,这是为什么呢?
我尝试用rect方法画矩形,监听mousedown和mousemove:
let startX, startY;
canvas.addEventListener('mousedown', (e) => {
startX = e.clientX;
startY = e.clientY;
canvas.addEventListener('mousemove', drawRect);
});
function drawRect(e) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.strokeRect(
startX,
startY,
e.clientX - startX,
e.clientY - startY
);
}
这样写的话拖动过程中矩形会不断重绘,但拖动速度快的时候边缘就会出现锯齿状的断层。试过给canvas加抗锯齿ctx.imageSmoothingEnabled = true没用,调整lineWidth到1.5px反而更明显。是不是跟绘制频率有关?
简单点的解决办法是:别用
mousemove直接画,改成用requestAnimationFrame做插值,或者至少把最后一点坐标缓存下来,每次画的时候从上一次的位置连到当前点。比如这样改一下:
这样每次只画一小段线,而不是每次都重画整个矩形,就算鼠标跳帧了,线也是连着的。
要是你真想画“矩形选框”那种效果(比如框选工具),也可以改成:每次
mousemove只更新一个临时的currentRect,然后在requestAnimationFrame里统一重绘,这样更稳:这招在 WP 里做富媒体编辑器、图床上传选区、后台图片裁剪都用过,稳得很。关键就是别指望 mousemove 像动画帧那么密,得自己兜住中间那几帧。
关键点:
1. 把矩形数据存到变量里,避免每次重绘时计算出错。
2.
redrawCanvas函数负责清屏和重绘,保证画面一致性。3. 加了个
isDrawing标志位,防止不必要的重绘。这样改了应该就不会有断层了。如果还卡,可能是浏览器性能问题,那就没办法了 😅