JS使用setInterval无输出,且收到非被动事件监听器违规提示
问题修复方案
线条无法显示问题修复
你对setInterval的传参逻辑有误:setInterval第一个参数要求传入待执行的函数引用,但你写的drawing.output(Canvas.ctx)是直接调用了output方法,将它的返回值(undefined)传给了setInterval,因此该方法只会在初始化时执行一次,不会按500ms的间隔定时重绘。
修复方式为传入箭头函数包裹执行逻辑:
// 修复前 window.setInterval(drawing.output(Canvas.ctx), 500); // 修复后 window.setInterval(() => drawing.output(Canvas.ctx), 500);
另外补充优化点:
- 你当前只监听了
mousedown、touchstart事件,只会在鼠标按下/触摸开始时记录一次坐标,要绘制连续线条需要额外监听mousemove/touchmove/mouseup/touchend事件,在指针移动过程中持续记录坐标 - 原代码中将
Drawing.prototype.output的定义放在了构造函数内部,每次实例化Drawing时都会重复覆盖原型方法,属于冗余写法,建议移到构造函数外部 - 触摸事件的坐标需要从
evt.changedTouches[0]中获取,否则移动端触摸绘制会失效
「Violation: Added non-passive event listener」警告修复
这个警告是浏览器针对触摸类事件的性能优化提示:对于touchstart、touchmove这类可能阻塞页面滚动的事件,如果你不会在监听器中调用evt.preventDefault(),需要显式将passive属性设为true,告诉浏览器可以直接执行滚动无需等待事件监听器执行完成。
将原来的触摸事件监听的第三个参数从布尔值改为配置对象即可:
// 修复前 Canvas.canvas.addEventListener("touchstart", catchAction, false); // 修复后 Canvas.canvas.addEventListener("touchstart", catchAction, {passive: true});
完整修复后代码
var Canvas = { canvas : undefined, ctx : undefined }; var Mouse = { x : [0], y : [0], isDrawing: false // 新增绘制状态判断,避免未按下时也记录坐标 }; function Drawing(width, colour){ this.width = width; this.colour = colour; } // 原型方法移到构造函数外,避免重复赋值 Drawing.prototype.output = function(ctx){ ctx.strokeStyle = this.colour; ctx.lineWidth = this.width; ctx.lineCap = 'round'; // 可选优化:让线条端点更圆润 for (var i = 0; i < Mouse.x.length-1; i++) { ctx.beginPath(); ctx.moveTo(Mouse.x[i], Mouse.y[i]); ctx.lineTo(Mouse.x[i+1], Mouse.y[i+1]); ctx.stroke(); } } Canvas.start = function () { function catchAction(evt) { // 兼容鼠标和触摸事件的坐标获取 const pageX = evt.changedTouches ? evt.changedTouches[0].pageX : evt.pageX; const pageY = evt.changedTouches ? evt.changedTouches[0].pageY : evt.pageY; // 按下/触摸开始时启动绘制 if(evt.type === 'mousedown' || evt.type === 'touchstart') { Mouse.isDrawing = true; Mouse.x.push(pageX); Mouse.y.push(pageY); return; } // 抬起/触摸结束时停止绘制 if(evt.type === 'mouseup' || evt.type === 'touchend') { Mouse.isDrawing = false; return; } // 移动过程中仅在绘制状态下记录坐标 if(Mouse.isDrawing) { Mouse.x.push(pageX); Mouse.y.push(pageY); } } Canvas.canvas = document.getElementById("myCanvas"); Canvas.canvas.width = Canvas.canvas.height = 600; Canvas.ctx = Canvas.canvas.getContext('2d'); let drawing = new Drawing(10, 'red'); // 补全全流程事件监听 Canvas.canvas.addEventListener("mousedown", catchAction, false); Canvas.canvas.addEventListener("mousemove", catchAction, false); Canvas.canvas.addEventListener("mouseup", catchAction, false); Canvas.canvas.addEventListener("touchstart", catchAction, {passive: true}); Canvas.canvas.addEventListener("touchmove", catchAction, {passive: true}); Canvas.canvas.addEventListener("touchend", catchAction, {passive: true}); // 修复setInterval传参 window.setInterval(() => drawing.output(Canvas.ctx), 500); }; document.addEventListener( 'DOMContentLoaded', Canvas.start);
内容的提问来源于stack exchange,提问作者Nic Oatridge
相关产品推荐
相关产品推荐

