likes
comments
collection
share

探索!用一个标签实现酷炫的css动画

作者站长头像
站长
· 阅读数 9

背景

那个最终实现上面,用了很多的标签在里面,有一些是效果需要,但是有一些是可以精简的。

于是想减少一下标签的使用来实现类似的效果,既然减少了,不如干脆一点,我们就用一个标签来尝试实现类似的效果。(不一完全一样的想效果,有些效果一个标签不好实现,下文会详细提到)

这是我们最终用单标签将要实现的效果。

老规矩,先分析一下效果,一共有六个部分,最外层圈,第二层圈,下面的一对圆环,上面的一对圆环,还有类流星雨动画的元素。

先把唯一的一个元素放好。

<div class="box"></div>

好,就这一个元素,html部分结束,下面全是css部分了!!!

最外层圈

这里第一反应应该是border,但是其实还有outline可以用,这里我们把border留给第二层用,我们第一层用outline来实现。

.box {
        width: 300px;
        height: 300px;
        border-radius: 50%;
        outline: 2px solid rgb(42, 153, 255);
        outline-offset: 10px;
      }

得到外面的圆环

探索!用一个标签实现酷炫的css动画

第二层圈

第二层我们用border, 然后把上下或者左右的边设为透明

box的样式上加上这些代码

{
 border: 5px solid rgb(42, 153, 255);
        border-left-color: transparent;
        border-right-color: transparent;
}

探索!用一个标签实现酷炫的css动画

下面的一堆圆环

上一篇文章里面,我们用了两种方式实现这个圆环

一种是conic-gradientmask,先利用角向渐变生成扇形,然后用mask遮住下面部分,得到圆环,然后重复多个,给每个不同的旋转角度。

第二种是repeating-conic-gradientmask,就是一次性生成带黑色间隔的扇形,然后mask遮住。

这里面我们还有第三种实现方式:

repeating-radial-gradientrepeating-conic-gradient

重复的径向渐变加重复的角向渐变来实现。

径向渐变可以得到一个完整的圆环,角向渐变可以得到黑色间隙的一堆小圆环。 这里面我们给box加上background

 background: repeating-radial-gradient(
            #000,
            #000 50%,
            transparent 50%,
            transparent 60%,
            #000 60%,
            #000 100%
          ),
          repeating-conic-gradient(
            rgb(42, 153, 255) 0,
            rgb(42, 153, 255) 4%,
            transparent 4%,
            transparent 5%
          );

探索!用一个标签实现酷炫的css动画

上面的一堆圆环

上面的一堆圆环实现起来其实和下面的一样,只是我们不能再用box的backgorund来实现了,因为有一个3d效果,需要沿着z轴做位移。

那我们其实还有两个工具没有用,那就是伪元素。这里我们先用一个::before

.box::before {
        content: '';
        position: absolute;
        width: 300px;
        height: 300px;
        top: 0px;
        left: 0px;
        background: repeating-radial-gradient(
            #000,
            #000 50%,
            transparent 50%,
            transparent 60%,
            #000 60%,
            #000 100%
          ),
          repeating-conic-gradient(
            rgb(42, 153, 255) 0,
            rgb(42, 153, 255) 4%,
            transparent 4%,
            transparent 5%
          );
        transform: translateZ(200px);
      }

探索!用一个标签实现酷炫的css动画

类流星雨元素

还剩下一个元素,我们就可以用另一个伪元素了,::after。 上一篇文章里面,我们用了一些元素来实现流星雨的动画,每一个元素代表其中一颗。这里我们只用一个伪元素实现的话,第一反应应该是用box-shadow来实现。

用box-shadow来实现对自身的多次复制,不过这里有一个缺陷,就是box-shadow默认是黑色,可以指定颜色但是不支持渐变。所以用box-shadow行不通,我们换一种方式来实现。

这里我们还是用repeating-linear-gradientmask来实现的。

重复的线性渐变实现几个自上而下的渐变色

探索!用一个标签实现酷炫的css动画

然后我们再用mask,获得色条

探索!用一个标签实现酷炫的css动画

.box::after {
        content: '';
        position: absolute;
        width: 300px;
        height: 300px;
        top: 0px;
        left: 0px;
        background: #fff;
        background: repeating-linear-gradient(
          to bottom,
          transparent 0,
          transparent 80px,
          rgba(42, 153, 255, 0.1) 80px,
          rgb(42, 153, 255) 130px
        );
        -webkit-mask: repeating-linear-gradient(
          to right,
          transparent 0px,
          transparent 80px,
          #000 80px,
          #000 82px
        );
        transform: rotateX(90deg);
        animation: line 2s linear infinite;
      }

到这里,我们就完整的用单标签实现了这样的一个动画效果。

全部代码如下:


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      body {
        background: #000;
        display: flex;
        align-items: center;
        justify-content: center;
        padding-top: 300px;
        transform: translateZ(-150px);
        transform-style: preserve-3d;
      }
      .box {
        width: 300px;
        height: 300px;
        transform-style: preserve-3d;
        position: relative;
        border-radius: 50%;
        border: 5px solid rgb(42, 153, 255);
        border-left-color: transparent;
        border-right-color: transparent;
        outline: 2px solid rgb(42, 153, 255);
        outline-offset: 10px;
        background: repeating-radial-gradient(
            #000,
            #000 50%,
            transparent 50%,
            transparent 60%,
            #000 60%,
            #000 100%
          ),
          repeating-conic-gradient(
            rgb(42, 153, 255) 0,
            rgb(42, 153, 255) 4%,
            transparent 4%,
            transparent 5%
          );
        animation: rotate2 2s linear infinite;
      }

      .box::before {
        content: '';
        position: absolute;
        width: 300px;
        height: 300px;
        top: 0px;
        left: 0px;
        background: repeating-radial-gradient(
            #000,
            #000 50%,
            transparent 50%,
            transparent 60%,
            #000 60%,
            #000 100%
          ),
          repeating-conic-gradient(
            rgb(42, 153, 255) 0,
            rgb(42, 153, 255) 4%,
            transparent 4%,
            transparent 5%
          );
        transform: translateZ(200px);
        animation: rotate1 2s linear infinite;
      }
      .box::after {
        content: '';
        position: absolute;
        width: 300px;
        height: 300px;
        top: 0px;
        left: 0px;
        background: #fff;
        background: repeating-linear-gradient(
          to bottom,
          transparent 0,
          transparent 80px,
          rgba(42, 153, 255, 0.1) 80px,
          rgb(42, 153, 255) 130px
        );
        -webkit-mask: repeating-linear-gradient(
          to right,
          transparent 0px,
          transparent 80px,
          #000 80px,
          #000 82px
        );
        transform: rotateX(90deg);
        animation: line 2s linear infinite;
      }

      @keyframes line {
        0% {
          transform: translateZ(-50px) rotateX(90deg) rotateY(0deg);
        }
        100% {
          transform: translateZ(200px) rotateX(90deg) rotateY(-360deg);
        }
      }

      @keyframes rotate1 {
        0% {
          transform: translateZ(200px) rotateZ(0deg);
        }
        100% {
          transform: translateZ(200px) rotateZ(-720deg);
        }
      }
      @keyframes rotate2 {
        0% {
          transform: rotateZ(0deg);
        }
        100% {
          transform: rotateZ(360deg);
        }
      }
    </style>
  </head>
  <body>
    <div class="box"></div>
    <script>
      var elem = document.querySelector('body')
      var isDragging = false // 用于判断是否正在拖动
      var initialX = 0 // 初始鼠标X坐标
      var initialY = 0 // 初始鼠标Y坐标
      var currentX = 0 // 当前鼠标X坐标
      var currentY = 0 // 当前鼠标Y坐标
      var initialRotationY = 0 // 初始旋转角度(Y轴)
      var initialRotationX = 0 // 初始旋转角度(X轴)

      elem.addEventListener('mousedown', function (e) {
        // 当鼠标按下时
        initialY = e.clientY // 获取初始鼠标Y坐标
        initialRotationY = parseInt(
          getComputedStyle(elem)
            .getPropertyValue('transform')
            .replace(/[^0-9-.,]/g, '')
            .split(',')[4]
        ) // 获取初始旋转角度(Y轴)
        initialRotationX = parseInt(
          getComputedStyle(elem)
            .getPropertyValue('transform')
            .replace(/[^0-9-.,]/g, '')
            .split(',')[5]
        ) // 获取初始旋转角度(X轴)
        isDragging = true // 设置isDragging为true,表示正在拖动
      })

      document.addEventListener('mousemove', function (e) {
        // 当鼠标移动时
        if (isDragging) {
          // 如果正在拖动
          currentY = e.clientY // 获取当前鼠标Y坐标
          var dy = currentY - initialY // Y轴方向移动的距离
          var newRotationY = initialRotationY + dy * -1 // 根据移动方向计算新的旋转角度(Y轴)
          console.log(111, dy, newRotationY)

          elem.style.transform = 'rotateX(' + newRotationY + 'deg)' // 设置元素的旋转角度
        }
      })

      document.addEventListener('mouseup', function () {
        // 当鼠标松开时
        isDragging = false // 设置isDragging为false,表示已经停止拖动
      })
    </script>
  </body>
</html>