pbakaus/scroller

Pinch to zoom not cross-browser

Opened this issue · 10 comments

akbr commented

Scroller's touch event API wants a "scale" property:

doTouchMove(touches, timeStamp, scale)

In the examples, this "scale" property is picked directly from the event (e.scale).

However, it seems that this is a webkit-specific property -- it doesn't exist in the current versions of mobile Chrome.

My workaround has been a third-party library (https://github.com/EightMedia/hammer.js), but it'd be nice if Scroller handled this on its own...

can you tell me how to fix this issue with hammer?

Hey,

I'm interested to know how to fix this issue using hammer as well. Also, if you can give me any clue about how to fix this issue for Scroller, I would love to help you to fix it.

Thanks in advance.

Best regards,
Miguel

NdYAG commented

Hope the following snippet would be helpful for those guys find this issue.
It works with Hammer.js 2.0. Test in current version of Android Chrome and iOS Safari.

var bodyHammer = new Hammer(document.querySelector('body'))
bodyHammer.get('pan').set({
    enable: true,
    direction: Hammer.DIRECTION_ALL
})
bodyHammer.get('pinch').set({
    enable: true
})

bodyHammer.on('panstart pinchstart', function(e) {
    var touches = e.srcEvent.touches
    if (touches[0] && touches[0].target && touches[0].target.tagName.match(/input|textarea|select/i)) {
        return
    }
    scroller.doTouchStart(touches, Date.now())
    e.preventDefault()
})

bodyHammer.on('panmove pinchmove', function(e) {
    var touches = e.srcEvent.touches
    scroller.doTouchMove(touches, Date.now(), e.scale)
})

bodyHammer.on('panend pinchend', function(e) {
    scroller.doTouchEnd(Date.now())
})

And what should scroller be? It returns undefined this way.
Thanks

NdYAG commented

It's your Scroller instance.

let scroller = new Scroller(() => {
  // the callback code
})

@NdYAG it's not work for me. actually it was worked a few days ago but its not working anymore.So,i'm getting error now;
in scroller.doTouchmove function :"Cannot read property 'length' of undefined"
what can i do?

edit: also it work all apple devices. but don't work android devices.

my code

 bodyHammer.on('panstart pinchstart', function (e) {
 	var touches = e.srcEvent.touches
 	if (touches[0] && touches[0].target && touches[0].target.tagName.match(/input|textarea|select/i)) {
 		return
 	}  
 	scroller.doTouchStart(touches, Date.now())
 	e.preventDefault()
 })
 bodyHammer.on('panmove pinchmove', function (e) {
 	var touches = e.srcEvent.touches;
 	scroller.doTouchMove(touches, Date.now(), e.scale)
 })
 bodyHammer.on('panend pinchend', function (e) {
 	scroller.doTouchEnd(Date.now())
 })
NdYAG commented

Hey @ahmetozantekin
Scroller and Hammer must have changed their APIs a lot during this long time.

Based on your error message, "Cannot read property 'length' of undefined", and the source code of scroller,

if (touches.length == null) {
I guess touches you passed for doTouchMove may be undefined. Make sure hammer.js handle panmove pinchmove as it did two years ago. Or you should pass touches from hammer.js in its new way.

@NdYAG thanks. yes i got it.
i just want zoom in and zoom out at every pinch move but touchmove's scale parameter is not reaction on android phone. for every pinch move , return "0" value.
then i write a solution yesterday, only use hammer's pinchmove function as control scale parameter. it works but not correctly.
i want accurate solution, use hammerjs or whatever.

here's my code,

document.addEventListener("touchmove", function(e) {
    __touches = e.touches;
    __timeStamp = e.timeStamp;

    bodyHammer.on('pinchmove', function(e) {
        __scale = e.scale;
        scroller.doTouchMove(__touches, __timeStamp, __scale);
        e.preventDefault();
    })

    scroller.doTouchMove(__touches, __timeStamp, __scale);
    e.preventDefault();	
}, false); 

@NdYAG and @ahmetozantekin actually the Scroller and Hammer APIs mentioned on the top of this thread by @NdYAG didn't change what has changed is that Chrome 55 added support for pointer events and in the way broke the old APIs for touch (see more at https://developers.google.com/web/updates/2016/10/pointer-events). There are lots of different issues opened on different libraries about it.

I got @NdYAG code working by doing a slightly change so that the code become:

var bodyHammer = new Hammer(document.querySelector('body'))
bodyHammer.get('pan').set({
    enable: true,
    direction: Hammer.DIRECTION_ALL
})
bodyHammer.get('pinch').set({
    enable: true
})

bodyHammer.on('panstart pinchstart', function(e) {
   // Here is the addition
    var touches = e.srcEvent.touches || e.changedPointers
    if (touches[0] && touches[0].target && touches[0].target.tagName.match(/input|textarea|select/i)) {
        return
    }
    scroller.doTouchStart(touches, Date.now())
    e.preventDefault()
})

bodyHammer.on('panmove pinchmove', function(e) {
    // Another change
    var touches = e.srcEvent.touches || e.changedPointers
    scroller.doTouchMove(touches, Date.now(), e.scale)
})

bodyHammer.on('panend pinchend', function(e) {
    scroller.doTouchEnd(Date.now())
})

thanks so much @alanrubin here's the answer is that i am looking for.