Smoothing animation in JS

Asked

Viewed 174 times

0

I am creating an application based on Vue.js. This application should contain some elements that are animated according to the mouse.

I created the animations in javascript and you can see that the elements are "tremendous" on the screen, you can see in the following video: https://youtu.be/BN-hyMMFO27M

All elements have absolute position and are animated by changing their position on the screen. Follow the code:

loadMouseMove: function () {
    this.resetarPosicoes();
    this.elementosMousemove = [];

    var elementos = document.getElementsByClassName('efeitomouse');
    for (var i = 0; i < elementos.length; i++) {

        var config = JSON.parse(elementos[i].getAttribute('mmconfig'));

        this.elementosMousemove.push({
            objeto: elementos[i],
            posicaoOriginal: {
                top: elementos[i].offsetTop,
                left: elementos[i].offsetLeft
            },
            fator: {
                x: config.fx,
                y: config.fy
            }
        });
    }
    this.mousemoveHabilitado = (elementos.length > 0);

    this.mousePosicaoAtual = {
        x: (this.tamanhoTela.width / 2),
        y: (this.tamanhoTela.height / 2)
    }

    this.mouseUltimaPosicao = {
        x: this.mousePosicaoAtual.x,
        y: this.mousePosicaoAtual.y
    }
},
resetarPosicoes: function () {
    for (var i = 0; i < this.elementosMousemove.length; i++) {
        this.elementosMousemove[i].objeto.style.left = '';
        this.elementosMousemove[i].objeto.style.top = '';
    }
},
mousemove: function (event) {

    app.mouseUltimaPosicao.x = event.x;
    app.mouseUltimaPosicao.y = event.y;

    if (app.mousemoveHabilitado) {
        cancelAnimationFrame(app.animationFrame);
        app.animationFrame = requestAnimationFrame(app.animarMouseMove);
    }
},
animarMouseMove: function () {
    var deltaX = app.mouseUltimaPosicao.x - app.mousePosicaoAtual.x;
    var deltaY = app.mouseUltimaPosicao.y - app.mousePosicaoAtual.y;
    var deslocamentoMax = 20;

    if (deltaX > 0) {
        app.mousePosicaoAtual.x += (deltaX > deslocamentoMax) ? deslocamentoMax : deltaX;
    } else {
        app.mousePosicaoAtual.x += (deltaX < -deslocamentoMax) ? -deslocamentoMax : deltaX;
    }

    if (deltaY > 0) {
        app.mousePosicaoAtual.y += (deltaY > deslocamentoMax) ? deslocamentoMax : deltaY;
    } else {
        app.mousePosicaoAtual.y += (deltaY < -deslocamentoMax) ? -deslocamentoMax : deltaY;
    }

    app.moverElementosMousemove(app.mousePosicaoAtual.x, app.mousePosicaoAtual.y);

    if (Math.abs(deltaX) > 10 || Math.abs(deltaY) > 10) {
        app.animationFrame = requestAnimationFrame(app.animarMouseMove);
    }
},
moverElementosMousemove(x, y) {
    var left = x - (app.tamanhoTela.width / 2);
    var top = y - (app.tamanhoTela.height / 2);

    for (var i = 0; i < app.elementosMousemove.length; i++) {
        var elemento = app.elementosMousemove[i];
        var px = elemento.posicaoOriginal.left + left * elemento.fator.x;
        var py = elemento.posicaoOriginal.top + top * elemento.fator.y;

        elemento.objeto.style.left = px + 'px';
        elemento.objeto.style.top = py + 'px';
    }
}

Is there any way to soften this movement so that this effect no longer occurs?

EDIT

https://codepen.io/anon/pen/jpVjxG

  • Put the rest of the code in html and css

  • Looks like a problem of rounding broken values.

  • If you reduce the speed of mouse movement, do the elements tremble? Just to know if the problem is in routine performance or calculation.

  • The ideal is always to use the property transform for animations on the X/Y axis on behalf of the Acceleration via Hardware.

  • how to sweat Transform via Javascript?

  • 1

    @Kazzkiq hardware will only be activated if you use properties that use the 3 render axes, i.e., transformZ, rotateZ, etc.

  • @Kazzkiq changed to use Transform and solved the problem, could create an answer to this question?

  • @Pilati done.

Show 3 more comments

2 answers

3


It is considered good practice to use the property transform CSS3 whenever you do some kind of CSS animation.

This is because certain properties CSS have their optimized rendering via hardware, making possible the use of the device GPU in animations, which greatly improves performance, especially in mobile devices.

So in your case, instead of using properties like top and left, you could use translate3d(x, y, z) to activate this type of optimization.

Example:

// No lugar de left e top
elemento.objeto.style.left = px + 'px';
elemento.objeto.style.top = py + 'px';

// Usar transform
elemento.objeto.style.transform = `translate3d(${px}px, ${py}px, 0)`;

-1

Probably if you add a CSS to the object that receives the properties left and top with a certain transition that is resolved.

transition: .1s all ease;
  • 1

    I’ve tried using the transition and it didn’t work. :/

Browser other questions tagged

You are not signed in. Login or sign up in order to post.