如何解决Javascript Canvas绘图代码在移动端浏览器无法运行的问题
问题原因
移动端touch事件的触点坐标不会直接挂载在event对象根属性上,单指操作时需要从event.touches[0]对象中读取clientX、clientY,你当前代码直接读取根event的坐标在touch事件触发时拿到的是undefined,自然无法绘制。
修复方案
在start、draw函数中先判断事件类型,优先取touch事件的触点坐标,再 fallback 到鼠标事件的坐标即可,修复后完整代码如下:
const canvas = document.getElementById("draw"); canvas.width = window.innerWidth - 60; canvas.height = 400; let context = canvas.getContext("2d"); context.fillStyle = "white"; context.fillRect(0, 0, canvas.width, canvas.height); let draw_color = "black"; let draw_width = "2"; let is_drawing = false; canvas.addEventListener("touchstart", start, false); canvas.addEventListener("touchmove", draw, false); canvas.addEventListener("mousedown", start, false); canvas.addEventListener("mousemove", draw, false); canvas.addEventListener("touchend", stop, false); canvas.addEventListener("mouseup", stop, false); canvas.addEventListener("mouseout", stop, false); // 统一获取坐标的工具函数 function getEventPos(event) { // 优先取touch事件的第一个触点坐标 if(event.touches && event.touches.length > 0) { return { x: event.touches[0].clientX - canvas.offsetLeft, y: event.touches[0].clientY - canvas.offsetTop } } // 鼠标事件直接取根属性 return { x: event.clientX - canvas.offsetLeft, y: event.clientY - canvas.offsetTop } } function start(event) { is_drawing = true; context.beginPath(); const pos = getEventPos(event) context.moveTo(pos.x, pos.y); event.preventDefault(); } function draw(event) { if (is_drawing) { const pos = getEventPos(event) context.lineTo(pos.x, pos.y); context.strokeStyle = draw_color; context.lineWidth = draw_width; context.lineCap = "round"; context.lineJoin = "round"; context.stroke(); } event.preventDefault(); } function stop(event) { if (is_drawing) { context.stroke(); context.closePath(); is_drawing = false; } event.preventDefault(); }
如果后续遇到绘制线条模糊的问题,可以把canvas的宽高属性乘以window.devicePixelRatio,再用CSS把canvas的显示尺寸设置回原来的数值即可解决。
内容的提问来源于stack exchange,提问作者TEN_KUNG
相关产品推荐
相关产品推荐

