Search code examples
javascriptanimationgsappopmotion

Converting Popmotion example to GreenSock


I'm trying to convert this Popmotion example to GreenSock.

https://codepen.io/popmotion/pen/xVeWmm

var SELECTOR      = '.box';
var velocityRange = [-1000, 1000];
var maxRotate     = 30;
var smoothing     = 100;

var box = ui.select(SELECTOR, {
    values: {
        x: 0,
        y: 0,
        rotateY: {
            watch: function (actor) {
                return actor.values.x.velocity;
            },
            mapFrom: velocityRange,
            mapTo: [-maxRotate, maxRotate],
            smooth: smoothing
        },
        rotateX: {
            watch: function (actor) {
                return actor.values.y.velocity;
            },
            mapFrom: velocityRange,
            mapTo: [maxRotate, -maxRotate],
            smooth: smoothing
        }
    }
});

var track2D = new ui.Track({
    values: {
        x: {},
        y: {}
    }
});

var springBack = new ui.Simulate({
    simulate: 'spring',
    spring: 500,
    friction: 0.3,
    values: {
        x: 0,
        y: 0
    }
});

$('body').on('touchstart mousedown', SELECTOR, function (e) {

    e.preventDefault();        
    box.start(track2D, e);

});

$('body').on('touchend mouseup', function () {

    box.start(springBack);

});

Being a total noob at GreenSock, is this easy to do? Does GreenSock have actors and simulators?


Solution

  • I have never used GreenSock to make continuous dynamic animations (maybe it is possible, I am not an expert in GreenSock). I prefer to left this library to make a specific animation. In the next example, I've tried to replicate the same Popmotion effect you have posted using my own calculations and I just use the animation library to return the box to its original place. I think that it can help you in your purpose:

    I've removed the vendor prefixes to make the code easier to read, but the CodePen example has the prefixes.

    HTML Code:

    <div id="container">
    
      <div class="box"></div>
    
    </div>
    

    CSS Code

    html {
        height: 100%;
    }
    
    body {
        background: #e25875;
        height: 100%;
    }
    
    #container {
        height: 100%;
        perspective: 700;
        perspective-origin: 50% 50%;
        position: relative;
        transform-style: preserve-3d;
        width: 100%;
    }
    
    .box {
        background: white;
        border-radius: 4px;
        height: 150px;
        left: 50%;
        margin-left: -75px;
        margin-top: -75px;
        position: absolute;
        cursor: pointer;
        top: 50%;
        will-change: transform;
        width: 150px;
    }
    

    JavaScript Code:

    //---Variables
    var doc = document,
        box = doc.querySelector(".box"),
        startX = 0,
        startY = 0,
        posX = 0,
        posY = 0,
        speedX = 0,
        speedY = 0,
        obj = {x: 0, y: 0, speedX: 0, speedY: 0};
    
    //---Main Events
    box.addEventListener("mousedown", startMove);
    doc.addEventListener("mouseup", stopMove);
    
    //---Start the movement
    function startMove (evt) {
    
        startX = evt.pageX;
        startY = evt.pageY;
    
        //---Add the mouse move events
        doc.addEventListener("mousemove", updatePosition);
    
    }
    
    //---Update variables
    function updatePosition (evt) {
    
        speedX = (evt.pageX - posX) * 5;
        speedY = (evt.pageY - posY) * 5;
    
        if (speedX < -45) { speedX = -45 }
        if (speedX > 45) { speedX = 45 }
        if (speedY < -45) { speedY = -45 }
        if (speedY > 45) { speedY = 45 }
    
        posX = evt.pageX;
        posY = evt.pageY;
    
        obj.x += (posX - startX - obj.x) * .15;
        obj.y += (posY - startY - obj.y) * .15;
        obj.speedX += (speedX - obj.speedX) * .15;
        obj.speedY += (speedY - obj.speedY) * .15; 
    
        updateTransform();
    
    }
    
    //---Stop movement, returns the box to its place
    function stopMove () {
    
        TweenLite.to(obj, 0.75, {
            ease: Elastic.easeOut.config(1, 0.3),
            x: 0,
            y: 0,
            speedX: 0,
            speedY: 0,
            onUpdate: updateTransform
        });
    
        doc.removeEventListener("mousemove", updatePosition);
    
    }
    
    //---Update the box transformations
    function updateTransform () {
    
        var transformStr = "translate(" + obj.x + "px, " + obj.y + "px) rotateX(" + (-obj.speedY) + "deg) rotateY(" + obj.speedX + "deg)";
    
        box.style.transform = transformStr;
    
    }
    

    Here you have a CodePen with a working example.

    EDIT: I've updated the CodePen to work with Touch Events.

    CodePen