JS implements parabolic animation

author: 陈家宾
email: [email protected]
date: 2018/2/24

In a small program project, you need to add a parabolic ball animation when you add a shopping cart.

Let me show you the renderings first.

analysis

This kind of animation with no fixed starting position naturally cannot use gif images, so it can only be implemented with native code

So what tools do we have to implement animation?

  • The applet provides JS API createAnimationto create animation
  • CSS transition

With the tool, let's take a look at what is a parabola.

Here we only discuss the level parabola, parabola from the level of principle, it is mathematically [level uniform, vertical acceleration of the movement], into code level is in animation timingFunction, the animation using the horizontal linearand vertical use of animationease-in

So we need to put this parabola animation broken down into two simultaneously conducted but different animation effects animation.

achieve

(1) The realization of applets

JS:

cartAnimation(x, y) { // x y 为手指点击的坐标,即球的起始坐标
    let self = this,
        cartY = app.globalData.winHeight - 50, // 结束位置(购物车图片)纵坐标
        cartX = 50, // 结束位置(购物车图片)的横坐标
        animationX = flyX(cartX, x), // 创建球的横向动画
        animationY = flyY(cartY, y) // 创建球的纵向动画
    this.setData({
          ballX: x,
          ballY: y,
          showBall: true
    })
    setTimeoutES6(100).then(() => { // 100 ms 延时,确保球已经到位并显示
        self.setData({
            animationX: animationX.export(),
            animationY: animationY.export(),
        })
        return setTimeoutES6(400) // 400 ms 是球的抛物线动画时长
    }).then(() => { // 400 ms 延时后隐藏球
        this.setData({
            showBall: false,
        })
    })
}

function setTimeoutES6(sec) { // Promise 化 setTimeout
    return new Promise((resolve, reject) => {
        setTimeout(() => {resolve()}, sec)
    })
}

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

function flyY(cartY, oriY) { // 垂直动画
    let animation = wx.createAnimation({
        duration: 400,
        timingFunction: 'ease-in',
    })
    animation.top(cartY).step()
    return animation
}

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>

translate optimization

As far as I know, use transform: translate()animation to achieve will be better than the top & left performance, but not so easy to achieve down slightly.

Research to study, and found that the method of translate is one step more than the method of top & left, that is, the translate displacement of the ball needs to be restored (otherwise translate has value all the time) to ensure that the next displacement starts from the clicked 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(() => {
        self.setData({
            animationDataX: animationX.export(),
            animationDataY: animationY.export(),
        })
        return setTimeoutES6(400)
    }).then(() => {
        this.setData({
            showBall: false,
            animationX: flyX(0, 0, 0).export(), // 还原小球位置,即 translate 恢复默认值
            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
}

HTML part unchanged

(2) Implementation of H5

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

<!DOCTYPE html>
<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 水平抛物线动画</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(()=>{
            $ball.style.top = window.innerHeight+'px';
            $ball.style.left = '0px';
            $ball.style.transition = 'left 1s linear, top 1s ease-in';
        }, 20)
    }
</script>
</html>

There is also an experience link, click me

So far, the realization of horizontal parabolic animation is almost introduced, hehe! !

This article is reproduced in: Ape 2048 https://www.mk2048.com/blog/blog.php?id=h0ij1k2hjcb

Guess you like

Origin www.cnblogs.com/baimeishaoxia/p/12722629.html