Native JS achieve a parabolic animation and motion blur effect

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

  • Scotland team
  • Author: Jason

Foreword

One day I received the goods sent to the micro-letter message. Small X, our business now need a similar drop animation add to the cart, after careful consideration of the organization, this requirement on to you. Then there was the article. This article does not describe how advanced the technology, the more I think of some of the principles of animation in doing animation, and some ideas on how to optimize the animation. Achieve results is as follows:

Picture quality is limited, please understand

technical analysis

There are a lot of front-end implementation animated way. Whether JS animation, CSS animation, Canvas or SVG animation animation, even animated GIF to implement a simple parabola is enough. However, considering the needs of business scenarios and playability, the final decision to use JS to achieve this animation.

Achieve analysis

In my opinion most of the animation, the final analysis, the application of mathematical formulas . The so-called parabolic motion animation is also nothing more than to let elements in line with the trajectory parabola.
Parabola equation: Y = A*X*X + B*X + CPerhaps we see this formula a bit strange. But once recited a physics teacher L(距离) = 1/2*A(加速度)*T*T(时间)surely we are certain to heart. The author is using this formula to complete the parabola animation.

Implementation

Step one get the start and end of the parabola

Due to the special nature of the business itself, it is necessary to obtain the absolute position of the element in the window when the user clicks on the item. I.e. the element coordinates relative to X region, Y browser visible. Here we recommend using the getBoundingClientRect()function to calculate the absolute position combined with the specific business. Of course, in some scenarios where you can use the mouse to click directly to the location or any other method to get the starting point of the animation.

Step two parabolic parameter setting

1. Acceleration

A speed determines the acceleration element in the setting direction (hereinafter are replaced with the vertical direction) change in speed. When the animation start and end are fixed, by the formula L(垂直距离) = 0.5 * A(加速度) * T * T(时间)it can be drawn at this time proportional to the square of the acceleration time T A .
It should be noted that the acceleration A positive move would have been to expand the vertical distance between the frame and the frame, so excessive acceleration A may lead to the end of the movie there is a small ball of light flashes .

2. X-axis and the time T initial speed

Parabolic animation in general we believe that the elements of fixed horizontal movement speed . Then the same formula by the L(水平距离) = T * Xspeed(水平速度)length of time can be drawn horizontal velocity Xspeed actually determines the execution of the animation.
Comprehensive concept of acceleration, we can draw the following conclusions:
certain when the start and end points of the animation, if we set the initial speed of the X axis is a fixed value, the animation length is fixed execution, this time to let the ball achieve the established position. A need to calculate the acceleration generated. The calculation formula is as follows:

// 确定动画起始点和终点
let XStart = 0, YStart = 0, XEnd = 1000, YEnd = 1000;
// 确定关键参数
let Xspeed = XX;
// 根据关键参数Xpeed计算动画时间与垂直加速度
let Time = (XEnd - XStart) / Xspeed; 
let A = 2 * (YEnd - YStart ) / (Time * Time); 

If needed animation execution of long fixed it?

// 确定关键参数
let Time = XX;
// 根据关键参数Time计算水平速度与垂直加速度
let Xpeed = (XEnd - XStart) / Time; 
let A = 2 * (YEnd - YStart ) / (Time * Time); 

If you need acceleration fixed it?
No, you do not need .....

3. Y-axis initial speed

The initial velocity of the Y-axis, i.e., vertical parabolic velocity thrown. I will set up a general initial Y axis speed is negative . At this time, there will naturally throw up and then falling animation, this time a little lively ... A formula for calculating the acceleration becomes:

let A = 2 * (YEnd - YStart - Yspeed * Time) / (Time * Time); 

It should be noted that the set of different ratios and Yspeed Xspeed can change the form of the curve . The rationale behind is: Yspeed and acceleration A (likely by Xspeed control) jointly decided to throw the ball the ball after rising phase can reach the highest point , and Xspeed determine the X-axis position at this time.

Step three let it move

JS conventional animation, we generally use setTimeOut or requestAnimationFram to achieve. Here we requestAnimationFram achieve a fixed duration animation execution example.

1. First generation pellets and determine the start and end of the animation, as well as key parameters

// 起点和终点请自由设定
let XStart = 0, YStart = 0, XEnd = 1000, YEnd = 1000; 
let Time = T;
let Xpeed = (XEnd - XStart) / Time; 
let Ypeed = -YY; 
let A = 2 * (YEnd - YStart - Yspeed * Time) / (Time * Time); 
// 生成元素
let Node = document.createElement('div');
// 自由控制形体,定位一般设定为Fixed
Node.className = 'myNode';
document.body.appendChild(Node);
Node.style.top = YStart + 'px';
Node.style.left = XStart + 'px';

2. Change the position of elements within the callback requestAnimationFram

// 记录元素实时位置
let nowX = XStart;
let nowY = YEnd;
// 单位时间
let loop = 0;
// 
let move = () => {
    if (nowY >= targetTop) {
        // 销毁实例的判断可自行设定
        Node.remove();
        return;
    }
    // 当前位置等于原始位置 + 单位时间内的位移
    nowX += Xspeed;
    // 
    nowY += (A * loop + Yspeed);
    requestAnimationFram(() => {
        Node.style.top = nowY + 'px';
        Node.style.left = nowX + 'px';
        loop++;
        move();
    });
};

3. The ball may exceed the destination point

According to code logic to stop the animation, the ball at the last shift, perhaps beyond the destination point that we have set. Next time we will determine setTimeOut in stop animation and destroy instances. Resolve as follows.

requestAnimationFram(() => {
    Node.style.top = Math.min(nowY, XEnd) + 'px';
    Node.style.left = Math.min(nowX, YEnd) + 'px';
    loop++;
    move();
});

By the way: here use Math.min () or Math.max () can achieve a lot of interesting animations themselves to discover the New World it .

How to achieve motion blur effect

Motion blur effect is achieved, the picture quality is limited, please understand

Ordinary achieve results, the picture quality is limited, please understand

What is motion blur?

Motion blur, this uses the definition of Baidu Encyclopedia of their 动态模糊或运动模糊(motion blur)是静态场景或一系列的图片像电影或是动画中快速移动的物体造成明显的模糊拖动痕迹。
author's understanding is that the residual visual information, that visual source current time (such as images, videos, brain supplement) remains in visual information on a moment. So what good is it? Continuous picture motion blur make the appropriate changes become more fluid and natural .

How to achieve motion blur?

First, we do a process of elimination, certainly can not put a movie ...
let us blur effect achieved in the dynamic read through 造成明显的模糊拖动痕迹. This means that if realized fuzzy drag marks can mimic the motion blur effect. So what is fuzzy drag effect?

This is a normal picture

This is a dynamic fuzzy picture

The author believes that the motion blur effect can be modeled as the same number of add elements around the element transparency gradient

Code

Before the code to achieve, we must first determine the goals we need to achieve. Parabolic animation ball into goal, namely to generate a number of transparency gradient around the ball movement of the ball . Adding specific location of the ball it? The author's idea is to insert the ball blur the ball between two frame position .

The first step in packaging

To achieve the original packaging in a function

let animat = (初始位置, 结束位置) => {
    ...参数设定
    // 位置变换
    nowX += Xspeed; 
    nowY += (A * loop + Yspeed);
    requestAnimationFrame(() => {
        Node.style.top = nowY + 'px';
        Node.style.left = nowX + 'px';
        loop++;
        move();
    });
}

The purpose is simply to generate the blur of the ball and also require the original ball position information synchronization.

The second step is generated blur

Thoughts: Every location blur ball to be associated with the real ball. (The same as the initial value set by the same natural trajectory of the ball) so we can not change the ball's true position, then translate it seems is a good choice.

let animat = (初始位置, 结束位置, 是否是残影) => {
    ...参数设定
    // 位置变换
    nowX += Xspeed; 
    nowY += (A * loop + Yspeed);
    requestAnimationFrame(() => {
        Node.style.top = nowY + 'px';
        Node.style.left = nowX + 'px';
        if (isShadow) {
            item.style.transform = `translate(${(0.5 * Xspeed)}px ,${-(0.5 * (A * loop + Yspeed))}px)`;
            item.style.opacity = 0.5;   
        }
    }
        loop++;
        move();
    });
}

Note that this step is essential to change the transparency . I recommend transparency values between 0.1 to 0.5 .

The third step generates a plurality of afterimage

If only a small ball, then generate a dynamic blur effect will not significantly. So we need to create a small number of ball control function.

createShadow(初始位置, 结束位置,  num) {
    for (let i = 0; i < num; i++) {
        animat(初始位置, 结束位置, true, i / (num + 1));
    }
},

animat function Change

let animat = (初始位置, 结束位置, 是否是残影, num) => {
    .....
    requestAnimationFrame(() => {
        ....
        if (isShadow) {
            item.style.transform = `translate(${-(num * Xspeed)}px ,${-(num * (A * loop + Yspeed))}px)`;
            item.style.opacity = (1 - num) * 0.5;   
        }
    }
    .....
    });
}

It's done.

Conclusion

If there puzzled about this article do not agree at it or you have a better idea, please leave a message in the message area. Exchange, and common progress.


More professional front-end knowledge, make the [2048] ape www.mk2048.com

Guess you like

Origin www.cnblogs.com/jiangshangbulao/p/11764409.html