Движение с жестове с hammerjs, css-transform и transform origin

Опитвам се да създам навигация с множество жестове в SVG среда. Успях, с примера, предоставен от Hammer.js, да внедря успешно плъзгане/пускане и щипка за мащабиране и завъртане чрез прилагане на трансформация на CSS3 атрибутите.

Трансформацията изглежда работи, но проблемът се появява, когато направя втора трансформация/завъртане и първоначалната точка изглежда е загубена и има скок между двете движения.

Ето jsfiddle с имплементация на проблема. Можете да опитате мултитъч (за завъртане / мащабиране), като задържите основния бутон.

http://jsfiddle.net/TdCcW/

canvas = {
    posX: 0,
    posY: 0,
    lastPosX: 0,
    lastPosY: 0,
    xImage: 0,
    yImage: 0,
    xLast: 0,
    yLast: 0,
    newPosX: 0,
    newPosY: 0,
    anchorX: 0,
    anchorY: 0,
    lastAnchorX: 0,
    lastAnchorY: 0,
    bufferX: 0,
    bufferY: 0,
    scale: 1,
    lastScale: undefined,
    rotation: 0,
    last_rotation: undefined,
    dragReady: 0,
    transformOrigin: '',
    initTouch: function () {
        Hammer.plugins.showTouches();
        Hammer.plugins.fakeMultitouch();

        var hammertime = Hammer(document.getElementById('container'), {
            transform_always_block: true,
            transform_min_scale: 1,
            drag_block_horizontal: true,
            drag_block_vertical: true,
            drag_min_distance: 0
        });

        var posX = 0,
            posY = 0,
            lastPosX = 0,
            lastPosY = 0,
            bufferX = 0,
            bufferY = 0,
            scale = 1,
            last_scale,
            rotation = 1,
            last_rotation, 
            dragReady = 0;

        hammertime.on('touch drag dragend transform', function (ev) {
            elemRect = document.getElementById('viewport');
            canvas.manageMultitouch(ev);
        });
    },
    manageMultitouch: function (ev) {

        switch (ev.type) {
            case 'touch':
                canvas.last_scale = canvas.scale;
                canvas.last_rotation = canvas.rotation;
                break;

            case 'drag':
                canvas.posX = ev.gesture.deltaX + canvas.lastPosX;
                canvas.posY = ev.gesture.deltaY + canvas.lastPosY;
                break;

            case 'transform':
                canvas.rotation = canvas.last_rotation + ev.gesture.rotation;
                canvas.scale = Math.max(1, Math.min(canvas.last_scale * ev.gesture.scale, 10));

                canvas.anchorX = (ev.gesture.center.pageX - canvas.lastPosX);
                canvas.anchorY = (ev.gesture.center.pageY - canvas.lastPosY);

                canvas.transformOrigin = canvas.anchorX + " " + canvas.anchorY;

                break;

            case 'dragend':
                canvas.lastPosX = canvas.posX;
                canvas.lastPosY = canvas.posY;

                break;
        }



        var transform =
            "translate3d(" + canvas.posX + "px," + canvas.posY + "px, 0) " +
            "scale3d(" + canvas.scale + "," + canvas.scale + ", 0) " +
            "rotate(" + canvas.rotation + "deg) ";

        elemRect.style.transform = transform;
        elemRect.style.oTransform = transform;
        elemRect.style.msTransform = transform;
        elemRect.style.mozTransform = transform;
        elemRect.style.webkitTransform = transform;

        elemRect.style.webkitTransformOrigin = canvas.transformOrigin;



    }
}

$(document).ready(function () {
    canvas.initTouch();
});

person jminguely    schedule 29.04.2014    source източник


Отговори (1)


Доколкото разбирам, вашият проблем е, че модифицирате трансформационния център (transform-origin). Разбирам какво се опитвате да постигнете, т.е. оставете новата модификация да се приложи в центъра на жеста за прищипване/завъртане. Въпреки това, като промените центъра на трансформация, вие също променяте центъра за всички трансформации, които сте приложили преди това, което води до скокливо поведение.

За да реализирате това, което искате, вероятно трябва да извършите някои матрични операции и да използвате атрибута css matrix. Теоретично бих предположил, че вие:

  • трябва да се запази текущата матрица на трансформация (TM)
  • when a new transformation is applied
    • move the TM by the negative transformation center of the gesture using matrix multiplication
    • матрица умножете TM с мащаба и позицията на жеста
    • преместете ТМ от центъра на положителна трансформация
    • приложете новата TM към атрибута css matrix

Надявам се това да помогне

Бенджамин

person Benjamin Mesing    schedule 08.05.2014