简体   繁体   English

如何正确使用 onpointermove 在 HTML5 Canvas 中绘制

[英]How to use onpointermove properly to draw in HTML5 Canvas

I'm using onpointerdown , onpointerup and onpointermove for handling HTML5 Canvas Freehand drawing and it works perfectly with mouse.我正在使用onpointerdownonpointeruponpointermove来处理 HTML5 Canvas Freehand 绘图,它与鼠标完美配合。 However, when I use a mobile it doesn't work, I have to add ontouchmove as shown in my working example.但是,当我使用手机时它不起作用,我必须添加ontouchmove ,如我的工作示例所示。

How can I get rid of ontouchmove and use just PointerEvents .我怎样才能摆脱ontouchmove并只使用PointerEvents

 const canvas = document.querySelector('canvas') const ctx = canvas.getContext('2d') // Same window dimensions canvas.width = window.innerWidth; canvas.height = window.innerHeight; // We need to track mouse/finger position and down/up let x, y, down // Start canvas.onpointerdown = e => { const { pageX, pageY } = e down = true x = pageX y = pageY } // End canvas.onpointerup = () => down = false // Move canvas.onpointermove = canvas.ontouchmove = e => { // Return if we havent finish yet if (!down) return const { pageX, pageY } = (e.touches && e.touches[0]) || e // Draw line ctx.beginPath() ctx.moveTo(x, y) ctx.lineTo(pageX, pageY) ctx.lineWidth = 1 ctx.stroke() // Update x = pageX y = pageY }
 body { margin: 0; padding: 0; background-color: #bbb; width: 100vw; height: 100vh; overflow: hidden; }
 <canvas></canvas>

Updated更新

I'm using a Samsung Galaxy A5 (2017) with Android 8 and Chrome 80.我正在使用搭载 Android 8 和 Chrome 80 的三星 Galaxy A5 (2017)。

Check this demo without the ontouchmove in a mobile.在手机中查看此演示,而不使用ontouchmove This is a screenshot from my device.这是我设备的屏幕截图

You can't: as there are legacy touch-based devices that does not support this API (for example, iOS 12 and below), you need to bind events for ontouchdown , ontouchmove , and ontouchend separately.不能:由于有不支持此 API 的旧式基于触摸的设备(例如 iOS 12 及更低版本),您需要分别为ontouchdownontouchmoveontouchend绑定事件。 You can check browser support for the pointer event API here .您可以在此处检查浏览器对指针事件 API 的支持

You can use window.PointerEvent to detect browser support for this API, and then return the correct event name you want to bind to:您可以使用window.PointerEvent来检测浏览器对该 API 的支持,然后返回您要绑定到的正确事件名称:

const hasPointerEvent = !!window.PointerEvent;
const pointerEventNames = {
  start: window.PointerEvent ? 'pointerdown' : 'touchstart',
  move: window.PointerEvent ? 'pointermove' : 'touchmove',
  end: window.PointerEvent ? 'pointerup' : 'touchend',
};

If you want to support IE10, you will need to add an additional check for window.MSPointerEvent , because IE10 only supports events prefixed with MS (and they are also PascalCased):如果要支持 IE10,则需要为window.MSPointerEvent添加额外的检查,因为 IE10 仅支持以MS为前缀的事件(并且它们也是 PascalCased):

function getPointerEventNames() {
  const o = {
    start: 'pointerdown',
    move: 'pointermove',
    end: 'pointerup'
  };

  if (!window.PointerEvent) {
    o.start = 'touchstart';
    o.move = 'touchmove';
    o.end = 'touchend';
  } else if (!!window.MSPointerEvent) {
    o.start = 'MSPointerDown';
    o.move = 'MSPointerMove';
    o.end = 'MSPointerUp';
  }
}
const pointerEventNames = getPointerEventNames();

Instead of doing canvas.onpointerdown = ... and then repeating the same logic for canvas.ontouchstart , you can use canvas.addEventListener instead.您可以使用canvas.addEventListener而不是做canvas.onpointerdown = ...然后为canvas.ontouchstart重复相同的逻辑。 The advantage of this is that you can then leverage on the dictionary pointerEventNames above, which will return the supported event names for the device you are on:这样做的好处是您可以利用上面的字典pointerEventNames ,它将返回您所在设备支持的事件名称:

// Define common handler
const onDown = (e) => {
  const { pageX, pageY } = e
  down = true
  x = pageX
  y = pageY
}
canvas.addEventListener(pointerEventNames.start, onDown);

And you repeat these for the other two events... see a proof of concept below:然后你对其他两个事件重复这些......请参阅下面的概念证明:

 const hasPointerEvent = !!window.PointerEvent; const pointerEventNames = { start: window.PointerEvent ? 'pointerdown' : 'touchstart', move: window.PointerEvent ? 'pointermove' : 'touchmove', end: window.PointerEvent ? 'pointerup' : 'touchend', }; const canvas = document.querySelector('canvas') const ctx = canvas.getContext('2d') // Same window dimensions canvas.width = window.innerWidth; canvas.height = window.innerHeight; // We need to track mouse/finger position and down/up let x, y, down // Start const onStart = (e) => { const { pageX, pageY } = e down = true x = pageX y = pageY } canvas.addEventListener(pointerEventNames.start, onStart); // End const onEnd = () => down = false; canvas.addEventListener(pointerEventNames.end, onEnd); // Move const onMove = (e) => { // Return if we havent finish yet if (!down) return const { pageX, pageY } = (e.touches && e.touches[0]) || e // Draw line ctx.beginPath() ctx.moveTo(x, y) ctx.lineTo(pageX, pageY) ctx.lineWidth = 1 ctx.stroke() // Update x = pageX y = pageY } canvas.addEventListener(pointerEventNames.move, onMove);
 body { margin: 0; padding: 0; background-color: #bbb; width: 100vw; height: 100vh; overflow: hidden; }
 <canvas></canvas>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM