Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Touch events are not being captured on the mobile device. #8849

Closed
7 tasks done
sejalaroraa1234 opened this issue Apr 20, 2023 · 25 comments
Closed
7 tasks done

Comments

@sejalaroraa1234
Copy link

sejalaroraa1234 commented Apr 20, 2023

CheckList

  • I agree to follow this project's Code of Conduct
  • I have read and followed the Contributing Guide
  • I have read and followed the Issue Tracker Guide
  • I have searched and referenced existing issues and discussions
  • I am filing a BUG report.
  • I have managed to reproduce the bug after upgrading to the latest version
  • I have created an accurate and minimal reproduction

Version

5.3.0

In What environments are you experiencing the problem?

Reactnative Mobile (android and IOS)

Node Version (if applicable)

19.6.0

Link To Reproduction

Using it in react native mobile app and it's private so we can't share the link.

Steps To Reproduce

Hey, I integrated fabric into my project and trying to capture the touch events of canvas but I'm not able to capture any touch event. I'm using fabric 5.3.0. I integrated it in react native by injected JS and displaying it by using react-native-webview. Below is my code

const canvas = new fabric.Canvas('canvas', {
selection:false,
height:1200,
width:1200,
backgroundColor: 'red',
zoomEnabled:true,
isDrawingMode:false,
isTouchSupported:true,
gestures: ['drag', 'zoom', 'rotate'],
preserveObjectStacking: true,
controlsAboveOverlay: true,
allowTouchScrolling: true,

});


canvas.loadFromJSON(${json}, canvas.renderAll.bind(canvas), function(o, object) {
  object.lockMovementX = true;
  object.lockMovementY = true;
  object.set('selectable', false);
  canvas.setViewportTransform([${minScale}, 0, 0, ${minScale}, ${translateX}, ${translateY}]);
  canvas.renderAll();
  })

  canvas.on('touch:gesture', function(e){
    ${console.log('touch:gesture event captured')}
    window.ReactNativeWebView.postMessage(JSON.stringify(e));
  });
  
  canvas.on('touchstart', function(e) {
    ${console.log('touchstart event captured')}
  });

  fabric.util.addListener(canvas.lowerCanvasEl, 'touchstart', function(e) {
    ${console.log('touchstart event captured')}
  });

In the above code, I'm using listener to capture the events but logs are not coming whenever I zoom or touch the canvas object on the mobile screen.

My canvas tag is kept like below in the html of webview:

<body><canvas id="canvas" touch-action="none"></canvas></body>

Cdn used: https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.0/fabric.min.js

Expected Behavior

The touch events should be captured whenever I touch the canvas or pinch zoom on it.

Actual Behavior

The touch events are not being captured. However, when I switch the selection property of the canvas to be true, the selected event of the canvas object is being listened!

Error Message & Stack Trace

No response

@timfrio
Copy link

timfrio commented May 15, 2023

similar situation, touch does not work on the phone

@BlackCat1397
Copy link

+1
canvas.on('mouse:down', function(opt) {...}); and other mouse related events work, but I want to use pinch gesture for zoom and canvas.on('touch:gesture', ... event does not work:|

@Yubayer
Copy link

Yubayer commented Aug 6, 2023

same probelm, touch event dosenot work

@dylanBcp
Copy link

+1
Same problem

@touxing
Copy link

touxing commented Sep 20, 2023

+1
Same problem

@asturur
Copy link
Member

asturur commented Sep 20, 2023

did you try to use the pointer events instead of touch?

enablePointerEvents: true

when initializing canvas.

the touch start event should fire whit enablePointerEvents: false only, while the pointer events will change the mouse events into pointerdown, pointerup and so on.

@harshpatel147
Copy link

harshpatel147 commented Oct 27, 2023

hey @asturur

import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild, ViewContainerRef } from '@angular/core';
import { fabric } from 'fabric';

@Component({
  selector: 'app-canvas-draw',
  templateUrl: './canvas-draw.component.html',
  styleUrls: ['./canvas-draw.component.scss']
})
export class CanvasDrawComponent implements OnInit, AfterViewInit {
  @ViewChild('mainHtmlCanvas') mainHtmlCanvas!: ElementRef;

  mainCanvas!: fabric.Canvas;
  isDragging: boolean = false;
  selection: boolean = true;
  lastPosX!: number;
  lastPosY!: number;
  isDrawingMode: boolean = false;

  ngAfterViewInit() {
    this.mainCanvas = new fabric.Canvas(this.mainHtmlCanvas.nativeElement, {
      hoverCursor: 'pointer',
      selection: this.selection,
      selectionBorderColor: 'blue',
      width: 500,
      height: 500,
      allowTouchScrolling: true,
      isDrawingMode: this.isDrawingMode,
    });

    this.mainCanvas.on('touch:gesture', (e) => {
      console.log('touch:gesture', e);
    });

    this.mainCanvas.on('touch:drag', (e) => {
      console.log('touch:drag', e);
    });

    this.mainCanvas.on('mouse:wheel', (opt) => {
      var delta = opt.e.deltaY;
      var zoom = this.mainCanvas.getZoom();
      zoom *= 0.999 ** delta;
      if (zoom > 20) zoom = 20;
      if (zoom < 0.01) zoom = 0.01;
      this.mainCanvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom);
      opt.e.preventDefault();
      opt.e.stopPropagation();
      var vpt = this.mainCanvas.viewportTransform ?? [];
      if (zoom < 400 / 1000) {
        vpt[4] = 200 - 1000 * zoom / 2;
        vpt[5] = 200 - 1000 * zoom / 2;
      } else {
        if (vpt[4] >= 0) {
          vpt[4] = 0;
        } else if (vpt[4] < this.mainCanvas.getWidth() - 1000 * zoom) {
          vpt[4] = this.mainCanvas.getWidth() - 1000 * zoom;
        }
        if (vpt[5] >= 0) {
          vpt[5] = 0;
        } else if (vpt[5] < this.mainCanvas.getHeight() - 1000 * zoom) {
          vpt[5] = this.mainCanvas.getHeight() - 1000 * zoom;
        }
      }
    });

    this.mainCanvas.on('mouse:down', (opt) => {
      var evt = opt.e;
      if (evt.altKey === true) {
        this.isDragging = true;
        this.selection = false;
        this.lastPosX = evt.clientX;
        this.lastPosY = evt.clientY;
      }
    });
    this.mainCanvas.on('mouse:move', (opt) => {
      if (this.isDragging) {
        var e = opt.e;
        var vpt = this.mainCanvas.viewportTransform ?? [];
        vpt[4] += e.clientX - this.lastPosX;
        vpt[5] += e.clientY - this.lastPosY;
        this.mainCanvas.requestRenderAll();
        this.lastPosX = e.clientX;
        this.lastPosY = e.clientY;
      }
    });
    this.mainCanvas.on('mouse:up', (opt) => {
      // on mouse up we want to recalculate new interaction
      // for all objects, so we call setViewportTransform
      this.mainCanvas.setViewportTransform(this.mainCanvas.viewportTransform ?? []);
      this.isDragging = false;
      this.selection = true;
    });
  }
}

I have to add support zoom and pan for touch devices. but touch:gesture, touch:drag touch related events not working for touch devices.

I'm using fabricJs v5.3.0 in Angular (Typescript).

I read your comment about enablePointerEvents: true during initilization . when I add this option. I'm getting error

Error: src/main/webapp/app/admin/fabricjs-canvas-draw/canvas-draw/canvas-draw.component.ts:158:7 - error TS2345: Argument of type '{ hoverCursor: string; selection: boolean; selectionBorderColor: string; width: number | undefined; height: number | undefined; allowTouchScrolling: true; isDrawingMode: boolean; enablePointerEvents: boolean; }' is not assignable to parameter of type 'ICanvasOptions'.
  Object literal may only specify known properties, and 'enablePointerEvents' does not exist in type 'ICanvasOptions'.

158       enablePointerEvents: true
          ~~~~~~~~~~~~~~~~~~~~~~~~~




✖ Failed to compile.
    "fabric": "^5.3.0",
    "@types/fabric": "^5.3.4",
    "typescript": "4.8.2",
    "angular": "14.2.0"

You can test it on stackblitz

@Jogii
Copy link

Jogii commented Dec 15, 2023

Touch events does not fire with fabricjs v5.3.0. Guys, Do we have any solution or workaround for this issue?
@sejalaroraa1234 @harshpatel147 @BlackCat1397 @touxing @dylanBcp @timfrio @Yubayer

@timfrio
Copy link

timfrio commented Dec 15, 2023

@Jogii, I just added a layer of divs on top of the fabric and transferred all touch action events with code

@harshpatel147
Copy link

harshpatel147 commented Dec 16, 2023

@Jogii, I just added a layer of divs on top of the fabric and transferred all touch action events with code

@timfrio I have to add support zoom and pan for touch devices. it is possible? can you share a working sample example?

Please check this Demo on stackblitz Zoom Works on Mouse Scroll, and Pan Works With Hold 'Alt' + Mouse Drag (Hold Down the mouse click and move mouse). but Zoom and pan not working for touch devices.

Please help me.

@Jogii
Copy link

Jogii commented Jan 4, 2024

@asturur @kangax @keyurpatel @melchiar @nimworks @ShaMan123 @stefanhayden @vinch
Guys, Is there any plan to fix the touch events bug? Kindly can anyone have a look at it with priority.

@ShaMan123
Copy link
Contributor

My plans for fabric are big and wide and can be seen with the list of ~80 open PRs
I can surely fix this issue or in fact suggest something a lot more robust but it won't necessarily enter fabric for some time.
@asturur what is the priority for this?

@ShaMan123
Copy link
Contributor

#9551 related

@niawjunior
Copy link

I use this one

hammerjs
image

RPReplay_Final1704369492.2.mp4

@kartiksolanki
Copy link

@niawjunior : Can you please show me the code inside hammerCanvas.on('pan') function ? I am able to use hammer js with fabricjs successfully but my panning is not as smooth as it is show in your video. I would greatly appreciate any help on how did you optimized it to work smoothly?

@touxing
Copy link

touxing commented Feb 1, 2024

I also use hammerjs to solution it.

image

@niawjunior
Copy link

@niawjunior : Can you please show me the code inside hammerCanvas.on('pan') function ? I am able to use hammer js with fabricjs successfully but my panning is not as smooth as it is show in your video. I would greatly appreciate any help on how did you optimized it to work smoothly?

Hi here for you

image image

@asnyder13
Copy link

I also previously had this issue. From what I remember, the package from npm was not built with gestures, so in my package.json I have

  "scripts": {
    ...,
    "postinstall": "cd node_modules/fabric && npm install && npm run build_with_gestures"
  },

@Smrtnyk
Copy link

Smrtnyk commented Feb 2, 2024

I also previously had this issue. From what I remember, the package from npm was not built with gestures, so in my package.json I have

  "scripts": {
    ...,
    "postinstall": "cd node_modules/fabric && npm install && npm run build_with_gestures"
  },

thats weird, I was expecting fabric to only ship with dist files and not source code

@asturur
Copy link
Member

asturur commented Feb 4, 2024

@Smrtnyk Fabric ships with both code and dist file because of previous building logic.
It still ships with everything because of it, and it may continue to do so, i m not sure what can be done with tools, but i don't that with the latest package.json the src are reacheable during import, but they should be with scripts during the install phase.

Is that an issue for some procedure?

Regarding touch:events in general, touch events should work and touch events are:

touchend
touchmove
touchstart

and touchcancel that we don't use.

if you prevent pointer events you can enable those too.

If you are asking for gesture implementations, i don't think those should be part of the core fabric functionality.

Is there even a still maintained good gesture library to make an example with? Because we could have a guide for integration yes, but last time i searched i didn't find a library that is used more than the others or that look better.
Last time i used Hammer.js and implementing gestures was quite easy

@ShaMan123
Copy link
Contributor

What gestures do we need?
I think we can add s scale + rotate gesture and the rest is trivial isn't it?

@krmanik
Copy link

krmanik commented Mar 4, 2024

I have implemented like this, may be helpful.

import Hammer from "hammerjs";

const minScale = 0.1;
const maxScale = 10;
let zoomScale = 1;
let currentScale = 1;

export const enableZoom = (canvas) => {
    canvas.on("mouse:move", onMouseMove);

    const hammer = new Hammer(canvas.upperCanvasEl);
    hammer.get("pinch").set({ enable: true });
    hammer.on("pinch pinchmove", ev => {
        currentScale = Math.min(Math.max(minScale, ev.scale * zoomScale), maxScale);
    });
    hammer.on("pinchend pinchcancel", () => {
        zoomScale = currentScale;
    });
};

export const disableZoom = (canvas) => {
    canvas.off("mouse:move", onMouseMove);

    const hammer = new Hammer(canvas.upperCanvasEl);
    hammer.get("pinch").set({ enable: false });
    hammer.off("pinch pinchmove pinchend pinchcancel");
};

const onMouseMove = (opt) => {
     if ((e.type === "touchmove") && (e.touches.length > 1)) {
        canvas.zoomToPoint({ x: canvas.width / 2, y: canvas.height / 2 }, currentScale);
        return;
    }
}

@AdemIssadWytopia
Copy link

Guys, please, where did you put those HammerJs scripts ? Can't find my way to make it work.

@ralphcode
Copy link

I also previously had this issue. From what I remember, the package from npm was not built with gestures, so in my package.json I have

  "scripts": {
    ...,
    "postinstall": "cd node_modules/fabric && npm install && npm run build_with_gestures"
  },

@asnyder13 Thanks. This solves the issue for me with 5.3.0.

@asturur
Copy link
Member

asturur commented Aug 18, 2024

There is a bit of confusion here about touch events.
drag/pinch/pan are not events, are names we give to multi touch/pointer combinations of down/move/up.
FabricJS core library does not take care of interpreting those as gestures, for which you can use something like Hammer.js indeed

@asturur asturur closed this as completed Aug 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests