【问题标题】:javascript + html5 canvas: drawing instead of dragging/scrolling on mobile devices?javascript + html5 画布:在移动设备上绘图而不是拖动/滚动?
【发布时间】:2019-09-05 19:44:50
【问题描述】:

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

在 Opera、Firefox、Chrome 等中运行良好(在台式电脑上试用过)。但是,如果我使用 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>

是否有一些特殊的样式或事件我必须添加到画布中,以避免在画布中滑动时拖动/滚动页面?

【问题讨论】:

    标签: javascript mobile html5-canvas draw drag


    【解决方案1】:

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

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

    在触摸启动方法中return false 很重要,否则会触发页面滚动。

    【讨论】:

    【解决方案2】:

    我将通过添加指向此答案的链接来添加到 Grassator 的答案中,该链接更深入地包含使此解决方案工作所需的代码:https://stackoverflow.com/a/16630678/5843693

    在我继续之前,请注意 Apple 已更改 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
       }
    };
    

    此外,EventListeners 是专门排序的,以便首先采用触摸输入:

    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 () {})中。

    【讨论】:

      猜你喜欢
      • 2021-12-28
      • 1970-01-01
      • 2021-09-02
      • 2012-08-16
      • 2017-02-23
      • 1970-01-01
      • 2014-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多