41
头图

A group of friends asked me how to use CSS to achieve the following Loading effect:

This is a very interesting question.

We know that with CSS, we can achieve such an animation very easily:

<div></div>
div {
    width: 100px;
    height: 100px;
    border-radius: 50%;
    border: 2px solid transparent;
    border-top: 2px solid #000;
    border-left: 2px solid #000;
    animation: rotate 3s infinite linear;
}
@keyframes rotate {
    100% {
        transform: rotate(360deg);
    }
}

The animation is as follows:

Compared with the required line loading animation, the above animation lacks the core point:

  • length of the line will change during the rotation movement.

Therefore, the difficulty here becomes, how to dynamically realize the change of the length of the arc line segment? Solving this problem basically solves the above-mentioned line transformation Loading animation.

This article will introduce some interesting ways to dynamically change the length of arc lines in CSS:

Method 1: Use a mask to achieve

The first method, which is also easier to think of, is implemented by using a mask.

We realize two semicircular lines, one can see the actual color, the other is same background color , relatively more coarse little semicircular lines, When the rates of movement of the two lines, from the visual , you can also see the dynamically changing arc lines.

Take a look at the schematic diagram and you will understand at a glance:

We replace the above red lines with white backgrounds, and the overall animation effect is very similar. The pseudo code is as follows:

<div></div>

div {
    width: 200px;
    height: 200px;
}
div::before {
    position: absolute;
    content: "";
    top: 0px; left: 0px; right: 0px; bottom: 0px;
    border-radius: 50%;
    border: 3px solid transparent;
    border-top: 3px solid #000;
    border-left: 3px solid #000;
    animation: rotate 3s infinite ease-out;
}
div::after {
    position: absolute;
    content: "";
    top: -2px; left: -2px; right: -2px; bottom: -2px;
    border-radius: 50%;
    border: 7px solid transparent;
    border-bottom: 7px solid #fff;
    border-right: 7px solid #fff;
    animation: rotate 4s infinite ease-in-out;
}
@keyframes rotate {
    100% {
        transform: rotate(0deg);
    }
}

The core is to realize two semicircular lines, one black and one background color, and the two lines move at different rates (controlled by animation time and easing). The effect is as follows:

Complete code you can bash -- CodePen Demo - Linear Loading

The two biggest problems with the above scheme are:

  1. If the background color is not a solid color, it will be exposed
  2. If the length of the line segment required to be displayed is greater than half a circle, it cannot be completed

Based on this, we can only find another way.

Method 2: Using the stroke-* capabilities of SVG

In many previous articles, it has been mentioned that with CSS and SVG, we can achieve various simple or complex line animations, such as simple:

Or custom complex line animations for complex paths:

> If you are interested in CSS/SVG to achieve line animation, but you don't know much about it, you can read my article -- [Web Animation] Introduction to SVG Line Animation

Here, we only need a simple SVG tag <circle> , with its CSS styles stroke-dasharray and stroke-dashoffset to easily accomplish the above effect:

<svg class="circular" viewbox="25 25 50 50">
  <circle class="path" cx="50" cy="50" r="20" fill="none" />
</svg>
.circular {
  width: 100px;
  height: 100px;
  animation: rotate 2s linear infinite;
}
.path {
  stroke-dasharray: 1, 200;
  stroke-dashoffset: 0;
  stroke: #000;
  animation: dash 1.5s ease-in-out infinite
}
@keyframes rotate {
  100% {
    transform: rotate(360deg);
  }
}
@keyframes dash {
  0% {
    stroke-dasharray: 1, 200;
    stroke-dashoffset: 0;
  }
  50% {
    stroke-dasharray: 89, 200;
    stroke-dashoffset: -35px;
  }
  100% {
    stroke-dasharray: 89, 200;
    stroke-dashoffset: -124px;
  }
}

Briefly explain:

  • stroke : Analogous to border-color in css, set the border color for svg graphics;
  • stroke-dasharray : The value is a set of arrays with no upper limit. Each number alternately represents the width of the line and the space;
  • stroke-dashoffset : The distance from the dash pattern to the start of the path.

We use stroke-dasharray to cut the original complete line into multiple segments, assuming that stroke-dasharray: 10, 10 represents such a graphic:

The first 10 is the length of the line segment, and the second 10 is the gap between the two visible line segments.

In the actual code, stroke-dasharray: 1, 200 means that it is between two 1px line segments, with an interval of 200px . Since the circumference of a circle with a 40px 40 * π ≈ 125.6px , which is less than 200 , there is only one point as shown in the figure:

Similarly, stroke-dasharray: 89, 200 means:

Through animation, let the line segment transition between these two states. The stroke-dashoffset is to move the line segment forward, and cooperate with the transform: rotate() rotation animation of the parent container, so that the visual effect, the line segment is always rotating in one direction. The result is as follows:

here for the complete code: 161e8c936f0516 CodePen Demo -- Linear loading

OK, some students will say, I don't want to introduce SVG tags, I just want to use a pure CSS scheme. Here, there is another pure CSS solution that utilizes CSS @property.

Method 3: Use CSS @property to make conic-gradient move

Here we need to use the ability of CSS @property to make the angular gradient that could not achieve the animation effect, move.

This method, I also mentioned in my article about CSS @property -- CSS @property makes the impossible possible

Normally, gradients cannot be animated, as follows:

<div></div>
.normal {
    width: 200px;
    height: 200px;
    border-radius: 50%;
    background: conic-gradient(yellowgreen, yellowgreen 25%, transparent 25%, transparent 100%); 
    transition: background 300ms;
    
    &:hover {
        background: conic-gradient(yellowgreen, yellowgreen 60%, transparent 60.1%, transparent 100%); 
    }
}

You will get such an effect. Since conic-gradient does not support transition animation, you will get a direct change from one frame to another:

Okay, let’s transform it with CSS @property custom variables:

@property --per {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 25%;
}

div {
    background: conic-gradient(yellowgreen, yellowgreen var(--per), transparent var(--per), transparent 100%); 
    transition: --per 300ms linear;
    
    &:hover {
        --per: 60%;
    }
}

Take a look at the effect after the transformation:

Here, we can make the gradient move dynamically, giving it the ability to animate.

We only need to introduce the mask and cut the middle part to realize the above line Loading animation. The pseudo code is as follows:

<div></div>

@property --per {
    syntax: "<percentage>";
    inherits: false;
    initial-value: 10%;
}

div {
    position: relative;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    animation: rotate 11s infinite ease-in-out;

    &::before {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        border-radius: 50%;
        background: conic-gradient(transparent, transparent var(--per), #fa7 var(--per), #fa7);
        mask: radial-gradient(transparent, transparent 47.5px, #000 48px, #000);
        animation: change 3s infinite cubic-bezier(0.57, 0.29, 0.49, 0.76);
    }
}

@keyframes change {
    50% {
        transform: rotate(270deg);
        --per: 98%;
    }
    100% {
        transform: rotate(720deg);
    }
}

@keyframes rotate {
    100% {
        transform: rotate(360deg);
        filter: hue-rotate(360deg);
    }
}

Here, I added filter: hue-rotate() way, so that when the line rotates, the color also changes, the final effect is as follows, this is a pure CSS solution:

The full code you can bash here: Linear Loading Animation

The only problem with this solution is that the current CSS @property compatibility is slightly less optimistic. Of course, the future can be expected.

At last

To sum up briefly, this article introduces three kinds of loading animations that realize dynamic arc line length changes. Of course, they have their own advantages and disadvantages, and the actual use is based on the actual situation. Sometimes, cutting pictures may also be a more time-saving way :)

Well, this is the end of this article, I hope this article will help you :)

If you want to get the most interesting CSS information, don't miss my account -- 161e8c936f07a0 iCSS front-end anecdote 😄

More wonderful CSS technical articles are summarized in my Github -- iCSS , which will be updated continuously. Welcome to click star to subscribe to the collection.

If you have any questions or suggestions, you can communicate more. Original articles are limited in writing and knowledge. If there are any inaccuracies in the article, please let me know.


chokcoco
12.3k 声望18.5k 粉丝