Author: Jiabin Chen Email: [email protected] Date: 2018/2/24Copy the code

JS to achieve parabolic animation

In the project of making unattended convenience applets, one day the product said to learn from a manufacturer’s product, adding parabolic ball animations to the shopping cart. All right, you’re the biggest product. Do it!

First let us have a look at the effect picture (in fact, it is already realized after the effect, by the way to advertise their own company haha)

Analysis of the

This kind of non-fixed starting position of animation, naturally cannot use GIF, so can only use native code implementation

So what tools do we have for animation?

  • Applets provide A JS APIcreateAnimationTo create an animation
  • CSS transition

Now that we have the tools, let’s see what a parabola is.

Here we only discuss the horizontal parabola, which means “horizontally uniform and vertically accelerated motion” in mathematical principle. When translated into code level, linear is used for horizontal animation and ease-In for vertical animation in animation effect timingFunction

So we need to break this parabolic animation into two simultaneous animations with different animation effects.

implementation

One, the realization of small procedures

JS:

cartAnimation(x, y) { // x and y are the coordinates of the finger click, i.e. the starting coordinates of the ball
    let self = this,
        cartY = app.globalData.winHeight - 50.// End position (cart image) ordinate
        cartX = 50.// The abscissa of the end position (cart image)
        animationX = flyX(cartX, x), // Create a horizontal animation of the ball
        animationY = flyY(cartY, y) // Create a vertical animation of the ball
    this.setData({
      	ballX: x,
      	ballY: y,
      	showBall: true
    })
    setTimeoutES6(100).then((a)= > { // a 100-second delay ensures that the ball is in place and displayed
        self.setData({
            animationX: animationX.export(),
            animationY: animationY.export(),
        })
        return setTimeoutES6(400) // 400 is the parabolic animation length of the ball
    }).then((a)= > { // Hide the ball after 400 seconds delay
        this.setData({
            showBall: false,})})}function setTimeoutES6(sec) { SetTimeout / / Promise
    return new Promise((resolve, reject) = > {
        setTimeout((a)= > {resolve()}, sec)
    })
}

function flyX(cartX, oriX) { // Horizontal animation
    let animation = wx.createAnimation({
        duration: 400.timingFunction: 'linear',
    })
    animation.left(cartX).step()
    return animation
}

function flyY(cartY, oriY) { // Vertical animation
    let animation = wx.createAnimation({
        duration: 400.timingFunction: 'ease-in',
    })
    animation.top(cartY).step()
    return animation
}
Copy the code

HTML:

<view animation="{{animationY}}" style="position:fixed; top:{{ballY}}px;" hidden="{{! showBall}}">
    <view class="ball" animation="{{animationX}}" style="position:fixed; left:{{ballX}}px;"></view>
</view>
Copy the code
Translate to optimize

As far as I know, transform: Translate () performs better than Top & Left, but it’s not that easy to implement.

It turns out that translate takes a step further than Top & Left. The translate shift needs to be reversed to ensure that the next translate shift starts at the click position

cartAnimation(x, y) {
    let self = this,
        cartY = app.globalData.winHeight - 50,
        cartX = 50,
        animationX = flyX(cartX, x),
        animationY = flyY(cartY, y)
    this.setData({
        leftNum: x,
        topNum: y,
        showBall: true
    })
    setTimeoutES6(100).then((a)= > {
        self.setData({
            animationDataX: animationX.export(),
            animationDataY: animationY.export(),
        })
        return setTimeoutES6(400)
    }).then((a)= > {
        this.setData({
            showBall: false.animationX: flyX(0.0.0).export(), // Restore the ball position, that is, translate restores the default value
            animationY: flyY(0.0.0).export(),
        })
    })
}

function flyX(cartX,oriX,duration) {
    let animation = wx.createAnimation({
        duration: duration||400.timingFunction: 'linear',
    })
    animation.translateX(cartX-oriX).step()
    return animation
}
function flyY(cartY,oriY,duration) {
    let animation = wx.createAnimation({
        duration: duration||400.timingFunction: 'ease-in',
    })
    animation.translateY(cartY-oriY).step()
    return animation
}
Copy the code

The HTML part doesn’t change

The realization of the H5

In addition to small programs, front-end daily development is more of course H5, the following I will use CSS3 transition method to implement


      
<html lang="en" style="width:100%; height:100%;">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width">
    <style>
        * {
            padding: 0;
            margin: 0;
        }
        #ball {
            width:12px;
            height:12px;
            background: #5EA345;
            border-radius: 50%;
            position: fixed;
            transition: left 1s linear, top 1s ease-in;
        }
    </style>
    <title>CSS3 horizontal parabola animation</title>
</head>
<body style="width:100%; height:100%;">
    <div id="ball"></div>
</body>
<script>
    var $ball = document.getElementById('ball');
    document.body.onclick = function (evt) {
        console.log(evt.pageX,evt.pageY)
        $ball.style.top = evt.pageY+'px';
        $ball.style.left = evt.pageX+'px';
        $ball.style.transition = 'left 0s, top 0s';
        setTimeout((a)= >{
            $ball.style.top = window.innerHeight+'px';
            $ball.style.left = '0px';
            $ball.style.transition = 'left 1s linear, top 1s ease-in';
        }, 20)}</script>
</html>
Copy the code

There are also experience link oh, click me

So far, the realization of horizontal parabola animation is almost introduced, hee hee!!