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

p5.js events confict with Swiper #6245

Closed
1 of 17 tasks
giodum opened this issue Jun 30, 2023 · 10 comments
Closed
1 of 17 tasks

p5.js events confict with Swiper #6245

giodum opened this issue Jun 30, 2023 · 10 comments

Comments

@giodum
Copy link

giodum commented Jun 30, 2023

Most appropriate sub-area of p5.js?

  • Accessibility
  • Color
  • Core/Environment/Rendering
  • Data
  • DOM
  • Events
  • Image
  • IO
  • Math
  • Typography
  • Utilities
  • WebGL
  • Build Process
  • Unit Testing
  • Internalization
  • Friendly Errors
  • Other (specify if possible)

p5.js version

1.6.0

Web browser and version

All browsers

Operating System

MacOSX - Ventura 13.0.1

Steps to reproduce this

Hi everybody, I am facing a very frustrating problem while using inside my Nuxt 3 project p5.js: there are some conflict problems with Swiper.js (I am using version 9.3.2).
It seems that p5.js listens to same name events triggered by Swiper.js, in particular touchstart, touchmove and touchend. So, when I move through the slides of a Swiper carousel I get an error from p5.js.

This is an example of the error I get in the console (same for touchmove and touchend):

p5.min.js:2 Uncaught TypeError: Cannot read properties of undefined (reading 'length')
    at e2.default._updateTouchCoords (p5.min.js:2:589678)
    at e2.default._ontouchstart (p5.min.js:2:590187)
    at Swiper.onAny (swiper-element-bundle.js:145:14)
    at events-emitter.js:87:24
    at Array.forEach (<anonymous>)
    at events-emitter.js:86:33
    at Array.forEach (<anonymous>)
    at Swiper.emit (events-emitter.js:84:17)
    at Swiper.onTouchStart (onTouchStart.js:111:10)

The error is generated inside p5.js in the function _updateTouchCoords, because the event e does not have touches property. I think this is due to the fact that the event e has been rised up by Swiper.

_main.default.prototype._updateTouchCoords = function (e) {
          if (this._curElement !== null) {
            var touches = [
            ];
            for (var i = 0; i < e.touches.length; i++) {
              touches[i] = getTouchInfo(this._curElement.elt, this.width, this.height, e, i);
            }
            this._setProperty('touches', touches);
          }
        };

I would really need to find a solution to prevent these errors. So I tried, but with no success, to detach the event listening (I will not use them).
Unfortunately documentation about that is not clear and it is really hard to understand where fix it.

I tried a lot of possibilities, no one with positive results:

  1. I tried to use _detatchListener method (ex. p5.Element._detachListener('touchEnd', p5Instance._curElement))
  2. I tried to remove event listener manually (ex. p5Instance.canvas.removeEventListener('touchend')) but it would need the exact name of the function to remove
  3. I tried to overrides events functions (ex. p5Instance._events['touchend'] = function () {} or overriding methods inside p5Instance prototype)

Would anybody have a solution to fix this problem?

Snippet:

import('p5').then((p5) => {
  const sketch = (p) => {
    let dimW = 0
    let dimH = 0

    p.setup = () => {
      p.createCanvas(width, height)
      p.angleMode(p.DEGREES)
      dimW = width / columns
      dimH = height / rows
    }

    p.draw = () => {
      p.clear()
      p.noStroke()
      p.rectMode(p.CENTER)

      // drawing code
      myDrawFunction()
    }
  }

  p5Instance = new p5.default(sketch, p5Container.value)
})
@giodum giodum added the Bug label Jun 30, 2023
@welcome
Copy link

welcome bot commented Jun 30, 2023

Welcome! 👋 Thanks for opening your first issue here! And to ensure the community is able to respond to your issue, please make sure to fill out the inputs in the issue forms. Thank you!

@davepagurek
Copy link
Contributor

As a quick hack, you could add this to your project:

const oldUpdateTouchCoords = p5.prototype._updateTouchCoords;
p5.prototype._updateTouchCoords = function(e) {
  if (e.touches) {
    oldUpdateTouchCoords.call(this, e);
  }
}

This will only call the actual p5 method if e.touches exists.

I'm not sure we want to deal with this in p5 core though, if this library is dispatching its own touch events that aren't actual DOM touch events. Maybe an issue should be opened on that repo?

@giodum
Copy link
Author

giodum commented Jun 30, 2023

As a quick hack, you could add this to your project:

const oldUpdateTouchCoords = p5.prototype._updateTouchCoords;
p5.prototype._updateTouchCoords = function(e) {
  if (e.touches) {
    oldUpdateTouchCoords.call(this, e);
  }
}

This will only call the actual p5 method if e.touches exists.

I'm not sure we want to deal with this in p5 core though, if this library is dispatching its own touch events that aren't actual DOM touch events. Maybe an issue should be opened on that repo?

Thank you for answering, unfortunately p5.prototype is undefined, so the code rise an error.
I tried to remanipulate it to get the same result, but however it does not work and I get always the same error of the issue.

This is what I tried, not working

const prototype = Object.getPrototypeOf(p5)
      const oldUpdateTouchCoords = prototype._updateTouchCoords
      prototype._updateTouchCoords = function (e) {
        if (e.touches) {
          oldUpdateTouchCoords.call(this, e)
        }
      }
      Object.setPrototypeOf(p5, prototype)

@davepagurek
Copy link
Contributor

Is that undefined inside of your import('p5').then((p5) => { ... }) callback too? If you haven't already, try putting the code block in there.

@limzykenneth
Copy link
Member

I'm not sure I fully understand but touchstart etc are native WebAPI events and is Swiper.js manually triggering these events somehow? That would not be compatible with any thing that would want to listen to the browser's native touch events if it has its own custom behaviour.

From what I can find, according to Swiper.js they no longer use these events and just rely on pointer events.

@giodum
Copy link
Author

giodum commented Jul 3, 2023

Is that undefined inside of your import('p5').then((p5) => { ... }) callback too? If you haven't already, try putting the code block in there.

Hi! Yes, p5.prototype is not defined, even inside the then part.
I think it is not the proper way to access the prototype of that object.
However even with the solution I showed you in the previous answer it did not work.

@giodum
Copy link
Author

giodum commented Jul 3, 2023

I'm not sure I fully understand but touchstart etc are native WebAPI events and is Swiper.js manually triggering these events somehow? That would not be compatible with any thing that would want to listen to the browser's native touch events if it has its own custom behaviour.

From what I can find, according to Swiper.js they no longer use these events and just rely on pointer events.

Honestly I am a little bit confused too and I am trying to clarify my thoughts, but no success till now.
When I have p5.js and Swiper in the same page it happens that, scrolling on Swiper carousel, it rises this error (same for ontouchmove and ontouchend)

Screenshot 2023-07-03 alle 15 23 56

Going deeper, here you can find the piece of code of Swiper.onTouchStart

Screenshot 2023-07-03 alle 15 24 14

This is the code of swiper-element-bundle.js

Screenshot 2023-07-03 alle 15 25 18

And this is the code pf p5.js

Screenshot 2023-07-03 alle 15 25 52

@limzykenneth
Copy link
Member

@giodum Just from the screenshots here I think what is happening is that Swiper have an event called touchStart (note uppercase S) which is perfectly fine and does not clash with native touchstart, however in onAny of the third screenshot, the name of the event is coerced to be lower case with name.toLowerCase() which means now the touchStart event becomes touchstart which is not allowed.

I don't know why that is done but in any case, this is an issue with Swiper as it should not be emitting touchstart events manually without attaching the right properties to the event itself.

@limzykenneth
Copy link
Member

Just found that this is a known issue in Swiper: nolimits4web/swiper#6450

I will close this issue for now as there is nothing to fix on p5.js' side. Thanks.

@giodum
Copy link
Author

giodum commented Jul 3, 2023

Thank you for your help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants