hammerjs / hammer.js

A javascript library for multi-touch gestures :// You can touch this
http://hammerjs.github.io
MIT License
24.12k stars 2.63k forks source link

On two finger touch rotate fires automatic before actual rotating fingers #914

Open sachingavas99 opened 8 years ago

sachingavas99 commented 8 years ago

When touch the screen to hold the element by two fingers, rotate event get fired instantly. Rotate event suppose to be fire only on actual rotating fingers. Important thing is that, When we touch element by two fingers it return different rotation all the time.

bellow is my code, please take a look on it and let me know.

         var mc = new Hammer( $( ".rotate" )[ 0 ], {
            tap :{enable:false}
         } );
        // create a pinch and rotate recognizer
        // these require 2 pointers
        var pinch = new Hammer.Pinch();
        var rotate = new Hammer.Rotate();

        // we want to detect both the same time
        pinch.recognizeWith(rotate);

        // add to the Manager
        mc.add([pinch, rotate]);

        var liveScale = 1;
        var currentRotation = 0;
        var prevRotation = 0;
        var rotation = 0;
        var scale=1, last_scale = $('.rotate').width(),
        rotation= 1, last_rotation, dragReady=0,
        lastgestureRotation = 0;
        $scope.rotateInProgress = false;
        var lastPosX = 0, lastPosY = 0, posX = 0, posY =0;

        mc.on("pinch pinchstart pinchend rotate rotatestart rotateend pan panend tap multitap", function(e) {
             e.preventDefault();

            switch( e.type ) {
                case 'rotatestart':
                    $scope.rotateInProgress = true;
                    last_scale = scale;
                    last_rotation = rotation;
                    break;

                case 'rotateend':
                    last_scale = scale;
                    last_rotation = e.rotation;
                    lastgestureRotation = e.rotation;

                    break;

                case 'rotate':
                    lastgestureRotation = e.rotation;
                    rotation = last_rotation + e.rotation;
                    //scale = Math.max(1, Math.min(last_scale * e.scale, 10));
                    break;
                case 'pinch':
                    scale =  scale = Math.max(1, Math.min(last_scale * e.scale, 10));

                    break;
                case 'pinchstart':
                    last_scale = scale;

                    break;
                case 'pinchend':
                    last_scale = scale;

                    break;
                case 'pan':
                    posX = e.deltaX + lastPosX;
                    posY = e.deltaY + lastPosY;

                    break;

                case 'panend':
                    lastPosX = posX;
                    lastPosY = posY;

                    break;
                case 'tap':
                    break;
                case 'multitap':
                    break;
            }

            $scope.setProfilePicLocation( { rotation : rotation, scale : scale } ); //set rotation
            $scope.setProfilePicLocation( null, { posX : posX+'px', posY : posY+'px' } ); //set location
taneltm commented 8 years ago

Can confirm (Android KitKat, Chrome) on the demo page. One clarification though, when the element is touched by 2 fingers, the initial rotation is not random. If the touch points are close to the same Y coordinate and the distance between the points is as big as possible, then the initial rotation is hardly noticable. But if the touch points are in a 45 deg angle and located in the corner of the image, then it's quite bad.

sachingavas99 commented 8 years ago

@tanelthm thanks for your valuable time

My issues has been solved. I was trying the code given at hammer.js examples. But actually as per my requirement, I suppose to have addition or subtraction of start and end rotations difference, instead of applying actual rotated angle to the element. So below is my updated code, It worked for me.

       $scope.setProfilePicLocation = function( rotateData, transformData ) {
            if( rotateData ) {
                $( ".photo-contener" ).css({'-webkit-transform' : 'rotate(' + rotateData.rotation + 'deg)' + ' scale3d(' + rotateData.scale + ', ' + rotateData.scale + ', 1 )' });
            }

            if( transformData ) {
                $( ".rotate-contener" ).css({'-webkit-transform' : ' translate3d(' + transformData.posX +',' + transformData.posY + ', 0 )' });
            }
        }

        mc = new Hammer( $( ".rotate" )[ 0 ], {
            tap :{enable:false}
         } );

        // create a pinch and rotate recognizer
        // these require 2 pointers
        var pinch = new Hammer.Pinch();
        var rotate = new Hammer.Rotate();

        // we want to detect both the same time
        pinch.recognizeWith(rotate);

        // add to the Manager
        mc.add([pinch, rotate]);

        var liveScale = 1;
        var currentRotation = 0;
        var prevRotation = 0;
        var rotation = 0;
        var scale=1, last_scale = $('.rotate').width(),
        rotation= 0, last_rotation, dragReady=0, start_rotation = 0;

        var lastPosX = 0, lastPosY = 0, posX = 0, posY =0;

        mc.on("pinch pinchstart pinchend rotate rotatestart rotateend pan panend tap multitap", function(e) {
            e.preventDefault();

            switch( e.type ) {
                case 'rotatestart':
                    last_scale = scale;
                    last_rotation = rotation;
                    start_rotation = e.rotation;
                    break;

                case 'rotateend':
                    last_scale = scale;
                    last_rotation = rotation;
                    break;

                case 'rotate':
                    var diff = start_rotation - e.rotation;
                    rotation = last_rotation - diff;

                    break;
                case 'pinch':
                    scale =  scale = Math.max(1, Math.min(last_scale * e.scale, 10));

                    break;
                case 'pinchstart':
                    last_scale = scale;

                    break;
                case 'pinchend':
                    last_scale = scale;

                    break;
                case 'pan':
                    posX = e.deltaX + lastPosX;
                    posY = e.deltaY + lastPosY;
                    break;

                case 'panend':
                        lastPosX = posX;
                        lastPosY = posY;
                    break;
                case 'tap':
                    break;
                case 'multitap':
                    break;
            }
            $scope.setProfilePicLocation( { rotation : rotation, scale : scale } ); //set rotation
            $scope.setProfilePicLocation( null, { posX : posX+'px', posY : posY+'px' } ); //set location

        });
dmreagan commented 8 years ago

This behavior is also easy to reproduce with the touch emulator. I consistently saw a 270 degree rotation from the rotatestart event before any real rotation had occurred. Fortunately, it was easy to compensate for using a method similar to @suchg above.

marty-krishner commented 8 years ago

+1

simongcc commented 8 years ago

+1

samehraban commented 7 years ago

+1

gibbok commented 6 years ago

good solution +1

laborc8 commented 5 years ago

I think this has been solved by: https://github.com/hammerjs/hammer.js/pull/982/files

I applied the patch and it worked great

munrocket commented 5 years ago

Here my solution https://codepen.io/munrocket/pen/dayZJg

ZhelinCheng commented 2 years ago

me too