Fig. 0. KDPV
Animation in the interface makes it obvious to change its state. For example, if unsuccessful, a long form is scrolled to an incorrectly filled field. Or an enlarged photo pushes the surrounding elements apart.
Without animation, it is harder to perceive sudden and sudden changes. However, the animation should be short and unobtrusive, so as not to disturb the user.
Animation seems natural when it repeats the usual movement of objects around the world. Under the cut, I'll tell you how I did the animation based on physical laws. See the finished result on the demo page (there one block follows another while moving the mouse).
Moving objects is described by changing the x coordinates over time t . If you try to pick up the function x ( t ) "by eye", you will spend a lot of time achieving smooth and natural movement. What to choose? Hyperbole? Parabola? Where to move it? How to turn?
For examples of movement it is best to turn to the objects of the surrounding world. The mathematical law of their movement is dictated by physics. Push the bar lying on the table. It travels a certain distance, slowing down by the action of friction. In a good approximation, the force of dry sliding friction is constant, and the dependence x ( t ) turns out to be a parabola. This slowdown can be used if the animation object has already moved at the initial moment.
Fig. 1. Braking by dry friction on a parabola
The force of viscous friction is proportional to the speed of the body. In this case, the body will move to the stopping point exponentially for an infinitely long time. If the exhibitor is distorted in order to limit the time of movement, such animation will seem unnatural. Due to difficulties in stopping at a reasonable time, one should not use the model of viscous friction only if the simulation of viscous friction itself is not the goal.
Fig. 2. Braking exponentially in a viscous medium
The pendulum deviated from the equilibrium position (or the weight on the spring) smoothly picks up speed, passes the equilibrium position and smoothly slows down. Then the movement is repeated in the opposite direction, and so on to infinity (if there is no friction). The schedule of such movement is a sinusoid. Periodic repetition is not particularly interesting to us, but the movement of the pendulum between the extreme points is smooth and natural.
Fig. 3. The motion of the pendulum in a sinusoid between the extreme points
In JS-libraries and CSS there are presets of easing-functions for creating special effects. Almost all blanks should be used in special cases with caution. Only a sinusoid is more or less universal.
First, the sinusoidal trajectory translates the body from one resting position to another. Secondly, the duration of such a movement is half the period. Movement is time limited. Duration does not depend on external circumstances and initial conditions. It depends only on the properties of the system itself and is determined by the ratio of stiffness and inertia.
Usually I choose the duration of the animation on a sine wave of 200 milliseconds. Such a duration is several times longer than the human response time. The animation is well marked, but does not have time to annoy.
Let's learn how to conduct a sinusoidal trajectory according to the initial conditions, the time of movement and the stop point.
Let the body rest at the initial and final moment of time. Then the tangents to the graph at the points t 1 and t 2 are horizontal, and the graph itself is the half-period of the sinusoid.
Fig. 4. Schedule of movement between two positions of rest
The equation describing the half-period of a sinusoid is easy to choose:
After the end of one animation, we can start another one again using this formula. But what if the new animation should start before the old one is over? To ensure smooth movement, we stop the current animation (blue line) and start a new animation (red line) with a non-zero initial speed:
Fig. 5. The schedule of movement with a non-zero initial speed
Without mathematical calculations, it is impossible to write a formula corresponding to the red line. Let's do this calculation.
The family of all possible sine waves is described by the equation
with four unknown parameters A , B , C and . I shifted the beginning of the time report to the point t 2 in order to immediately get rid of the second term. Indeed, the derivative
must be zero because the tangent at t 2 is horizontal. This is possible when B = 0.
Because then substituting
in (1), we get
. From here we exclude C :
Differentiate to find speed
We know the position x 1 and velocity v at the initial moment of time:
From this system of equations, you need to find A and . It's time to introduce a new variable
instead
. Its meaning is the phase difference of the sinusoid at the start and end point. For example, for the graph in fig. four
because on the gap
Fits half the sinusoid. In fig. five
, because
less than half the period.
After substitution and small transformations, we arrive at the system
Let us divide by first the first equation by the second:
Parameter on the right side is known in advance. It determines the desired nature of the movement. If a
, then the initial speed is small, the body must first accelerate. If a
, the initial speed is great, the body should slow down.
Trigonometric functions on the left side are reduced to the half-angle tangent. As a result, we have a nonlinear equation for k :
Analyze its solutions can be on the graph. Draw a graph of the left and right side for some values of the parameter :
Fig. 6. Graphic solution of equation (2)
Let's discuss the resulting solutions.
Consider point A. This solution exists when and corresponds to that shown in Figure 5:
. As was expected,
. In the zero speed limit
, the red line will coincide with the axis of ordinates, the point A will go along the tangent to infinity. In this limit
. So far everything is going right.
Point C corresponds to the value . This happens when the body moves forward at the first moment of time, and you have to move backwards. Now
. Movement is described by a fragment of a sinusoid, larger than a half-period, but smaller than the period:
. The body slows down, stops, moves backwards and stops at the required place.
From the graph you can see that when point B falls into range
. The body will pass along a sinusoid more than the full period of oscillations
. The reason for such a strange decision is that the stopping point is too close compared to the characteristic distance v ( t 2 - t 1 ). Therefore, to hold a sine wave without an additional stop and return will not work.
We solved the mathematical problem of carrying out a sinusoid, but life didn’t become easier. First, to determine the parameters of the sine wave, it is necessary to solve the nonlinear equation (2). Hi, iterative methods! Secondly, the equation has an infinite number of solutions, and the required solution does not always exist.
These difficulties arose from the fact that we fixed the duration of the animation at exactly 200 milliseconds. However, nothing terrible will happen if the animation lasts for, say, 180 milliseconds. Or even 250 milliseconds. It is more important for us to stop at a given place, and we sacrifice the exact duration of the animation to simplify the calculations.
Weaken the requirements for the duration of the animation, we will do the trick. Suppose we have an approximate solution nonlinear equation (2). It is an exact solution to an equation with a different parameter.
It corresponds to another time of the end of the animation:
Now the unknown parameters of the trajectory A and elementary express through
and
.
I selected an approximation suitable for our purposes to equation (2):
The blue solid line corresponds to the exact equation (2), and the red dotted line corresponds to its approximation:
Fig. 7. Comparison of the exact relation (2) and its approximation
And in the case of I suggest to take
slightly more than 1/2, and shorten the animation time to avoid bounces and returns.
The code and spherical usage example is on the demo page . Move your mouse and see how the black block follows the orange.
The described scheme is used in the finished product. I developed it for synchronous scrolling of the source code and a preview in the markdown and latex math text editor .
The idea and the initial implementation found on the demo page js-parser markdown-it . In their version, the animation turned out torn and braking. There are several reasons for this:
$(...).stop(true).animate({scrollTop: ...}, 100, 'linear')
. Instead of smooth graphics it turns out broken.jQuery().stop().animate()
slows down compared to requestAnimationFrame()
.onscroll
events are onscroll
, the next more often than 50 milliseconds. In my version there is no such problem. Sequential onscroll
events adjust the position of the breakpoint and do not slow down the animation.In order to achieve high-quality animation that is important for a product, I worked out a calculation method based on physical equations, and implemented it through a special browser requestAnimationFrame()
method. The method works well with any scrolling: the PageUp / PageDown keys, through moving the scroll bars, mouse wheel, touchpad, touchscreen.
Source: https://habr.com/ru/post/283284/