JavaScript + HTML5画布:如何在移动设备上绘图而不是拖动/滚动?

13

我正在使用html5画布和一些javascript(onmousedown / move / up)在网页上创建简单的绘图板。

在Opera,Firefox,Chrome等桌面PC上测试时,它工作得很好。但是如果我使用iPhone访问此页面,在尝试在画布上绘制时,它会拖动或滚动页面。

对于其他页面内容来说,这没问题,在移动浏览器中通过向上或向下滑动页面可以像平常一样导航。但是否有一种方法可以禁用画布上的此行为,以便移动访问者也能够在其上实际绘制一些东西?

以下是一个最简示例供您参考:

<html><head><script type='text/javascript'>
function init()
{
  var canvas = document.getElementById('MyCanvas');
  var ctx = canvas.getContext('2d');
  var x = null;
  var y;
  canvas.onmousedown = function(e)
  {
    x = e.pageX - canvas.offsetLeft;
    y = e.pageY - canvas.offsetTop;
    ctx.beginPath();
    ctx.moveTo(x,y);
  }
  canvas.onmouseup = function(e)
  {
    x = null;
  }  
  canvas.onmousemove = function(e)
  {
    if (x==null) return;
    x = e.pageX - canvas.offsetLeft;
    y = e.pageY - canvas.offsetLeft;
    ctx.lineTo(x,y);
    ctx.stroke();
  }  
}
</script></head><body onload='init()'>
<canvas id='MyCanvas' width='500' height='500' style='border:1px solid #777'>
</canvas></body></html>

在canvas中,我是否需要添加特殊的样式或事件来避免在滑动canvas时拖动/滚动页面?

2个回答

11

iPad / iPhone没有鼠标事件。你需要使用touchstarttouchmovetouchend。这些事件可能有多个触摸点,因此你需要像这样获取第一个触摸点:

canvas.ontouchstart = function(e) {
  if (e.touches) e = e.touches[0];
  return false;
}

在触摸开始的方法中重要的是使用return false,否则会触发页面滚动。


啊,明白了。以前从没注意过这些。谢谢! - Sheldon Pinkman
1
在Android上这个不起作用,但是你可以按照规范使用e.preventDefault();,规范链接为http://www.w3.org/TR/touch-events/#the-touchstart---------event - lapo

2
我会在Grassator的回答基础上加上一个链接,该链接详细介绍了制作此解决方案所需的代码:https://dev59.com/wXLYa4cB1Zd3GeqPVkbg#16630678
在我继续之前,请注意苹果已经改变了iOS处理滚动的方式。为了处理这种变化,需要添加一些额外的函数;感谢Christopher Vickers分享这个方法。
function preventDefault(e) {
    e.preventDefault();
}
function disableScroll() {
    document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
function enableScroll() {
    document.body.removeEventListener('touchmove', preventDefault);
}
<最初的回答>canvas的方法都是以绘图方式调用的,就像这样:
var drawer = {
   isDrawing: false,
   touchstart: function (coors) {
      ctx.beginPath();
      ctx.moveTo(coors.x, coors.y);
      this.isDrawing = true;
      disableScroll(); // add for new iOS support
   },
   touchmove: function (coors) {
      if (this.isDrawing) {
         ctx.lineTo(coors.x, coors.y);
         ctx.stroke();
      }
   },
   touchend: function (coors) {
      if (this.isDrawing) {
         this.touchmove(coors);
         this.isDrawing = false;
      }
      enableScroll(); // add for new iOS support
   }
};

此外,EventListener会按照特定顺序进行排序,以便首先处理触摸输入:

最初的回答

var touchAvailable = ('createTouch' in document) || ('onstarttouch' in window);

if (touchAvailable) {
   canvas.addEventListener('touchstart', draw, false);
   canvas.addEventListener('touchmove', draw, false);
   canvas.addEventListener('touchend', draw, false);
} else {
   canvas.addEventListener('mousedown', draw, false);
   canvas.addEventListener('mousemove', draw, false);
   canvas.addEventListener('mouseup', draw, false);
}

最后,在代码末尾添加另一个EventListener可以防止“弹性”滚动。
document.body.addEventListener('touchmove', function (event) {
   event.preventDefault();
}, false);

所有这些都放置在window.addEventListener('load', function () {})中。最初的回答。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接