Nicola Piermattei
Nicola Piermattei

Reputation: 29

Touch event only happens once when drawing on canvas

Basically, i have to draw on a canvas in my web application based on Angular 7. Mouse drawing works just fine, while the touch part will work just for the first stroke and then never draws again.

What i have tried is binding the event on a mouse event following some guides, literally copy-pasting code and modifying just the variables names. I can currently only test the touch events on the Chromium IPadPro simulator.

the preventdefault and stopimmediatepropagation calls make no difference if there are there or not

fromEvent(canvasE1, 'touchstart').pipe(switchMap(() => {
        return fromEvent(canvasE1, 'touchmove').pipe(
          takeUntil(fromEvent(canvasE1, 'touchend')),
          takeUntil(fromEvent(canvasE1, 'touchcancel')),
          pairwise()
        );
      })).subscribe((res: [TouchEvent, TouchEvent]) => {
        const rect = canvasE1.getBoundingClientRect();

        const prevPos = {
          x: res[0].touches[0].clientX - rect.left,
          y: res[0].touches[0].clientY - rect.top
        };
        res[0].preventDefault();
        res[0].stopImmediatePropagation();

        const currentPos = {
          x: res[1].touches[0].clientX - rect.left,
          y: res[1].touches[0].clientY - rect.top
        };
        res[1].preventDefault();
        res[1].stopImmediatePropagation();

        this.drawOnCanvas(prevPos, currentPos);
      });

private drawOnCanvas(prevPos: { x: number, y: number }, currentPos: { x: number, y: number }) {

    if (!this.twoDimensionalContext) {
      return;
    }
    this.twoDimensionalContext.beginPath();

    if (prevPos) {
      this.twoDimensionalContext.moveTo(prevPos.x, prevPos.y);
      this.twoDimensionalContext.lineTo(currentPos.x, currentPos.y);
      this.twoDimensionalContext.stroke();
    }
  }

the drawOnCanvas function works perfectly fine with the mouse events, so i think that's not the problem. the Mouse part just works perfectly fine and doesn't fire up when the touch device is detected.

Upvotes: 1

Views: 484

Answers (1)

goncami
goncami

Reputation: 25

To event preventDefault, you need to add map into fromEvent, after takeUtil, for example, changing this:

    return fromEvent(canvasE1, 'touchmove').pipe(
        takeUntil(fromEvent(canvasE1, 'touchend')),
        takeUntil(fromEvent(canvasE1, 'touchcancel')),
        pairwise()
     );

to

        return fromEvent(canvasE1, 'touchmove').pipe(
          takeUntil(fromEvent(canvasE1, 'touchend')),
          takeUntil(fromEvent(canvasE1, 'touchcancel')),
          map( (event) => {
              event.preventDefault();
              event.stopPropagation();
              return event; 
          }),
          pairwise()
        );

Upvotes: 1

Related Questions