Writing in the front

The example of this article is also my CSS animation enlightenment, the idea comes from an article of Digging friends, there is a link at the end of the article, but only to provide ideas, so I plan to achieve a wave, by the way to share the experience of animation production process. It’s kind of proof that when you open your mind, animation is really easy.

JS animation from the previous article? It’s not as hard as you think. With 150 lines of code to take you to a new world, this article continues to take you to the beauty of animation.

Click here for a preview and click here for the GitHub repository

Example based on CSS3, not considering browser compatibility, more to help you open your mind, you can actually do bad places to correct, DIY. The CSS in the project is compiled with LESS. How do I use LESS in common projects? , the answer is on LESS Chinese official website. Is it convenient to introduce a less. Js CDN? It will make you love CSS.

Here’s what it looks like:

Now let’s get down to business and show you how to draw these two batteries.

The waves battery

If you want to play CSS animation well, the smoke screen is indispensable. What is a smoke screen?

Overflow: hidden;

<div id="battery1">
	<div class="battery-anode"></div>
	<div class="battery-body">
		<div class="wave"></div>
		<div class="wave" style="transform: rotate(90deg); opacity: 0.7;"></div>
		<div class="wave" style="transform: rotate(45deg); opacity: 0.9;"></div>
		<div class="charge"></div>
	</div>
</div>
Copy the code

Here, battery-anode is the positive electrode, battery-body is the battery body, wave is the wave, and charge is the square color block used for charging. As you can see from the picture, the waves are a distraction created by the rotation of several squares. The important thing to note here is the hierarchical relationship of these divs, and only the right hierarchical relationship can show the right effect.

Here is the animation:

// @keyframes rotateAndUp {0% {margin-top: -50px; } 100% { margin-top: -215px; transform: rotate(360deg); }} @keyframes charge {0% {margin-top: 100px; background-color: red; } 50% { margin-top: 25px; background-color: orange; } 100% { margin-top: -50px; background-color: limegreen; }}Copy the code

I believe that when you write CSS, you will instinctively give up thinking when you see the words @include, @keyframes, @media and so on. It doesn’t matter, SO do I. I always feel like these things are incredibly complicated. But the truth is, once you realize how powerful it is, it’s hard to put it down.

After the animation is finished, you need to add it to the DOM element you want to apply, using the ANIMATION property of CSS.

animation: rotateAndUp 8s linear infinite;
Copy the code

Set infinite to keep moving.

Pay attention to

One thing to note here is that 0% of @keyframes is the initial state of the animation, which is the state that the element will change to immediately when the animation starts. If the same attribute is defined outside the frame, it will be overwritten. In the rotateAndUp animation above, you might think:

Why do I define CSS in a DOM structure alone? Why is transfrom: rotate() not included in 0% of the frame animation?

First, add transform: rotate() to define the different initial states for the wave to rotate. Secondly, if written in 0%, then as soon as the animation starts, the corresponding element will immediately change to the state defined in 0%, the same attribute will be overwritten, the same effect will not be achieved, all waves will remain the same. So if there are attributes that need to be transformed, just write them in 0%. The most common is the transform attribute. In addition, complex animations are mentioned here. Normal animations, such as hover effect, can be perfectly performed directly by Transform + Transition.

details

Careful friends can find that CSS animation is executed in a loop, but every time it ends, it jumps back to the original position and starts again. Sometimes the desired effect is not this, nor is it simply reverse, but a smooth transition. If you’ve written @keyframes, see if I’m right?

For example, a circular 360° rotation and moving up and down animation is generally very easy, but when I control the animation @keyframes, I always fail to achieve the expected effect. At the end of the animation, I always jump frames or shake, but you can feel helpless. How do I prevent frame hops? This is actually a skill, the author repeatedly test summary found that it is not difficult, very simple, do you want to know? Go ahead and look at the next one, the big ball at the top of the Android Charge animation.

Android Charging animation

The animation, at first glance, you’re probably most interested in how these dots move, and why do they create this gooey effect

Train of thought

First, the stickiness effect between the small spheres is achieved by using a powerful CSS filter: Filter, using filter’s Contrast + Blur. Use blur to blur the edges of elements and contrast to enhance the contrast. Blur is added to the elements, and contrast is added to the background. The background must have a color, and it is better to distinguish it from the color of the elements for better contrast. In this example, the background color is white. Here’s an example: How do you see a hair? Put it on a piece of paper.

The effect is as follows:

How does the ball move?

CSS implementation

Using CSS, it is not difficult to think of, we need to draw a number of dots of different sizes in advance, by setting different times, the cycle can be executed. This method needs to draw more circles, need many DIV containers, DOM structure may be relatively large, and careful observation can see the law of animation. In order to echo the object oriented thought decomposition animation mentioned in the JS animation article, I decided to use JS implementation. It’s the irregular animation that makes sense, don’t you think?

Pure CSS can also be implemented. If you are interested in digging friends, you can try it out. Both methods have their advantages and disadvantages. If you have any results, please leave them in the comments section and let me have a look.

CSS + JS implementation

As mentioned in the previous article, how to break down an animation? Object-oriented thought analysis shows that a ball is an object, and we can abstract out a class to draw the ball and insert it dynamically. Use math.random () to compute random positions and radius sizes. The Circle class describes the attributes of the dot, and the Run class controls the creation, insertion, deletion and movement of the dot.

Each animation can return a Promise object. In some cases, asynchronous flow control is involved. It is very useful and lightweight. Jj.animate () is also used in this article

Here’s the DOM structure:

<! -- battery container --> <div class="battery-container"> <! --> <div class="big-circle"> 98.7% < / div > <! -- container for dots --> <div class="circle-container"<div class= "> <div class=""decoration"></div> <! Battery base --> <div class="bottom"></div>
    </div>
</div>
Copy the code

To prevent the display of large circles from being affected by the contrast filter, write them separately and then position them on the dot container. Because it is written separately, the large circle does not have the fusion effect. Therefore, a hidden layer is added in the dot container and positioned under the large circle to help it achieve the fusion effect. This call what? Yes, a smoke screen.

LESS code

@radius and so on are pre-defined variables, which is the convenience of LESS. When using variable definition, you only need to modify the variable to modify all references to the variable, which is very extensible.

.big-circle { width: @radius; height: @radius; line-height: @radius; border-radius: @radius; top: -@radius / 2; font-size: 30px; position: absolute; z-index: 10; Text-align: center; text-align: center; background-color: white; animation: breathe 3s linear infinite; }. Circle-container {width: 100%; height: 100%; position: relative; background-color: white; // contrast(20); // decoration {width: @radius; color: RGB (50, 50, 50); height: @radius; border-radius: @radius; position: absolute; background-color: @limegreen; filter: blur(6px); animation: upAndDown 2s ease infinite; Circles {filter: blur(6px); Background-color: @limegreen; background-color: @limegreen; position: absolute; } // base. Bottom {width: @radius; height: @radius / 3; border-radius: 50% e('/') 100% 100% 00; // To prevent slashes from being compiled by LESS into division, write position: absolute; bottom: -1px; background-color: @limegreen; filter: blur(6px); }}Copy the code

@ keyframes frame animation

The above frame animation anti – jump frame pass now tell you:

@keyframes breathe {from, to {box-shadow: 3px 3px 20px @limegreen inset, -3px-3px @limegreen; } 25% { box-shadow: -3px 3px 20px @limegreen inset, 3px -3px @limegreen; } 50% { box-shadow: -3px -3px 20px @limegreen inset, 3px 3px @limegreen; } 75% { box-shadow: 3px -3px 20px @limegreen inset, 3px -3px @limegreen; }} @keyframes upAndDown {from, to {top: -@scale/2 + 3px; } 50% { top: -@scale/2 + 8px; }}Copy the code

In fact, it is very simple, we just need to ensure the same state at the beginning and end of the animation, to prevent frame skipping, smooth transition. From, to {} (or 0%, 100% {}) together. In fact, the principle is very simple, the animation after the change in the middle eventually changed back, since changed back, naturally is a smooth transition.

Here we remove from to see the effect, also remove to:

The transition back to the beginning was very abrupt
Don’t underestimate CSS

My initial thoughts were:

  1. Modelled on the.decorationAdd a circle at the bottom
  2. Add animation to hide circle rotation and scaling to simulate breathing effects
  3. Change the shadow, more vivid

But then I remembered the new feature of CSS3: box-shadow. I can have multiple shadows, which means I can change the inner and outer shadows at the same time, and the shadow replaces the hidden circle THAT I was going to add, which is really convenient.

About the shadow

When you are ready to use it in frame animation, be sure to sketch and study the parameters. Poor parameter planning can result in inconsistent speeds at each stage of the animation, which is strange. Take the first two basic parameters, the offset of the X and Y axes. The first thing you need to understand is that the coordinate system is positive downward to the right. What appears to be a rotation animation is actually a smoke screen that transforms the left and right and upper and lower shadows respectively. Yes, it’s a smoke screen again.

According to the rule of coordinates in the browser, we can calculate the coordinates when the inner shadow is in the four corners as shown below, and the outer shadow is the same:

Good results or to try more, more grinding

According to 0% ~ 100% of the middle four frames, fill the above four coordinates in turn, it doesn’t matter successively, see what you want the effect of the appearance. I chose the effect that the inner shadow rotates clockwise, so my coordinates fill order is from the top left corner, clockwise. The outer shadow and inner shadow are reversed by swapping a set of diagonal coordinates.

This is the origin of my above coordinates, but also because they are almost dizzy, just find paper and pen to plan a good. Now let’s talk about how to draw these balls.

Circle the class

Responsible for describing the dot property, corresponding to the Snowflake class from the previous article. This class is still pretty simple.

class Circle {
	constructor () {
		this.init()
	}
	init () {
		this.radius = random(15, 30)
		this.vy = random(1500, 3000, true// Use time to describe the speed, the longer the time, the slower the speed // the initial x-coordinate of x, need to be controlled within this range, This.x = random(circle.range, circle.width - circle.range) // This.dom = this.create()}create () {
		let c = this.dom || document.createElement('div'// Reuse existing elements c.style.width = this.radius +'px'
		c.style.height = this.radius + 'px'
		c.style.borderRadius = this.radius + 'px'
		c.style.left = this.x - this.radius / 2 + 'px'// Center point c.style.bottom ='12px'C.classlist.add ()'circles')
		return c
	}
}
Copy the code

thinking

Why do we need the init() method to initialize a property, rather than writing it directly from constructor?

No, the properties of the object involved in the animation need to be updated periodically. With this method, instances of the class can reset all properties by calling the init() method in the prototype to achieve random effects.

Run class

class Run {
	constructor() {
		this.container = document.querySelector('.circle-container') // Set static value, Describe ball canvas range Circle. The width = this. The container. The offsetWidth / / canvas width Circle. The height = this. The container. The offsetHeight / / ball moving maximum height Circle. Range = Circle. Width / 4 // Left/right spacing this.circles = this.createcircle (10) This.run ()} createCircle (num) {this.run()} createCircle (num) {let circles = new Set()
		for (let i=0; i<num; i++) {
			circles.add(new Circle())
		}
		returnCircles} animation (circle) {this. The container. The appendChild (circle. The dom) / / use jQuery. Here the animate () methodreturn $(circle.dom).animate({
			bottom: Circle.height + 'px'}, {duration: circine. vy, // Call the requestAnimationFrame after the animation is completed. Complete: () => {circle.init() // Refresh property to remove mission completion ball, prevent infinite insertion of this.animation(circle)}})}runForEach (item => {this.animation(item)})}}Copy the code

Same idea, same object oriented, we completed an animation effect. Maybe we’ll actually use this animation in the future. If you’re interested, you can turn it into a wheel, packaged as a small plug-in like snow.js in the previous article, with configurable interfaces for simple animation.

The last

CSS, a lot of seemingly advanced animation, are created through the smoke screen. If you read this article carefully, you will learn something, even if you don’t understand the code. If you can copy the code from GitHub and study it, you will learn more. Interested digg friends can contribute some code to the warehouse, or the comment area dry up, are very welcome.

Finally finished, writing all afternoon, back pain. If you find anything interesting, give me a thumbs up (Kazilan big eyes). Thank you very much.

reference

  1. 【 Nuggets 】 Skillfully use CSS to achieve cool charging animation
  2. LESS Chinese official website
  3. The animation library Velocity. Js