记录--一个炫酷的css动画

news2024/11/16 5:55:35

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

最近有一个需求,要我实现一个动画效果,效果如下

简单分析了一下效果,是一个3d的效果,首先是一个圆,接着是两段圆环,第三层是一堆小圆环,最里面是一些线上运动,有着渐变色的矩形。

第一层的圆环很简单。

第二层的圆环其实也挺简单的,只要在设置了border-radius为50%之后,把左右或者上下边的颜色设置为transparent就可以了

第三层的一对小圆环其实是最复杂的

我们可以先实现一个小圆环

.annulus {
        width: 200px;
        height: 200px;
        background: conic-gradient(
          rgb(25, 234, 253) 0,
          rgb(25, 234, 253) 4%,
          transparent 4%
        );
        border-radius: 50%;
        -webkit-mask: radial-gradient(
          transparent,
          transparent 50%,
          #000 50%,
          #000 100%
        );
      }

这里主要用到了两个属性,conic-gradient mask

conic-gradient

conic-gradient 是一种 CSS 渐变方式,它用于创建一个锥形渐变,从圆心向外辐射。与线性渐变和径向渐变不同,锥形渐变是以中心点为起点,按照一定的角度进行渐变。它的语法如下:

conic-gradient([starting position], color-stop1, color-stop2, ...)
  • starting position:锥形渐变的起始位置,默认值是 0deg,表示从顶部开始。你可以使用角度值或关键词 from 来指定起始位置,例如 45degfrom left.
  • color-stop:颜色停止点,定义渐变的颜色和位置。

这里我们把其他地方都设置为透明,只在4%的范围内设置颜色,这样会得到一个扇形。

mask

mask 是一个 CSS 属性,用于创建遮罩效果,即在元素上应用一个遮罩图像或图像源,以控制元素的可见性。它可以让你根据遮罩图像的不透明度来决定元素的哪些部分是可见的,哪些部分是隐藏的。

mask 属性有两种主要用法:

  1. 使用图像作为遮罩:
.masked-element { mask: url("mask-image.png"); } 

这将使 .masked-element 元素的内容受到 mask-image.png 图像的遮罩影响。图像的不透明部分将允许元素内容显示,而图像的透明部分将隐藏元素内容。

  1. 使用线性渐变或径向渐变作为遮罩:
.masked-element { mask: linear-gradient(to right, transparent 0%, black 100%); }

这里我们只需要把前面部分设置为透明,后一部分设置为不透明,加上这样的遮罩效果,就能得到我们需要的一个扇形了。

我们用radial-gradient和mask的结合就可以实现这样的效果

radial-gradient

radial-gradient 是 CSS 中的一个渐变函数,用于创建径向渐变效果。它允许你在一个元素的背景中创建从一个颜色到另一个颜色的渐变,呈现出一种从中心向外的径向效果。

语法如下:

background: radial-gradient([shape] [size] at [position], color-stop1, color-stop2, ...);

radial-gradient 是 CSS 中的一个渐变函数,用于创建径向渐变效果。它允许你在一个元素的背景中创建从一个颜色到另一个颜色的渐变,呈现出一种从中心向外的径向效果。

语法如下:

background: radial-gradient([shape] [size] at [position], color-stop1, color-stop2, ...);
  • [shape] 定义渐变的形状,可以是 circle(圆形)或 ellipse(椭圆形)。
  • [size] 定义渐变的大小,可以是 closest-sidefarthest-sideclosest-cornerfarthest-corner 或一个长度值。
  • [position] 定义渐变的中心位置,可以使用关键字(如 centertop left)或百分比/长度值组合。
  • color-stop 是颜色和位置的组合,用于定义渐变的颜色变化。

到了这里,我们实现了一个小圆环,那么怎么实现一堆按照圆环排列的小圆环呢,那其实就是在生成一堆这样的元素,然后给每次元素不同的rotate角度,就能实现了。

接着是最内层的向上运动的流星动画 这里其实也比较简单,只要画一个小矩形,然后背景加上渐变色,然后加上自下而上的动画就可以实现一个矩形,然后复制多个出来,在动画上要设置不同的持续时间和延时,就能达到随机的效果。

全部代码如下,没有用sass和js去动态生成样式和元素 下面的js是鼠标上下拖动时候会翻转。

<!DOCTYPE html>
<html>
  <head>
    <style>
      html {
        background: black;
      }
      .container {
        width: 300px;
        height: 300px;
      }
      .main1 {
        width: 500px;
        height: 500px;
        transform: translateZ(-150px);
        transform-style: preserve-3d;
      }
      .main2 {
        width: 300px;
        height: 300px;
        transform-style: preserve-3d;
        transform: rotateX(60deg);
        position: relative;
      }
      .flex {
        display: flex;
        align-items: center;
        justify-content: center;
      }
      .positon {
        position: absolute;
      }
      .center {
        top: 50%;
        left: 50%;
        transform: translateX(-50%) translateY(-50%);
      }
      .firstCircle {
        width: 400px;
        height: 400px;
        border-radius: 50%;
        border: 3px solid rgb(42, 153, 255);
      }
      .secondCircle {
        width: 350px;
        height: 350px;
        border-radius: 50%;
        border: 10px solid rgb(42, 153, 255);
        border-color: rgb(42, 153, 255) transparent;

        animation: rotate1 3s linear infinite;
      }
      .thirdCircle {
      }
      .fourthCircle {
        width: 300px;
        height: 300px;
        transform: translateX(-50%) translateY(-50%) translateZ(30px);
        animation: rotate2 3s linear infinite;
      }
      .annulusContent {
        width: 100%;
        height: 100%;
        position: relative;
        transform-style: preserve-3d;
      }
      .bar {
        width: 280px;
        height: 300px;
        background: transparent;
        top: 50%;
        left: 50%;
        transform: translateZ(150px) translateX(-50%) translateY(-50%)
          rotateX(90deg);
        display: flex;
        gap: 20px;
        overflow: hidden;
      }
      .line {
        width: 3px;
        height: 100px;
        background: linear-gradient(
          to top,
          rgb(69, 164, 254),
          rgba(42, 153, 255, 0.1)
        );
      }
      .line1 {
        animation: line1 1s linear infinite;
      }
      .line2 {
        animation: line1 0.5s 0.2s linear infinite;
      }
      .line3 {
        animation: line1 1.5s 0.5s linear infinite;
      }
      .line4 {
        animation: line1 1.3s 1s linear infinite;
      }
      .line5 {
        animation: line1 1.6s 0.3s linear infinite;
      }
      .line6 {
        animation: line1 2s 0.4s linear infinite;
      }
      .line7 {
        animation: line1 1.2s 0.6s linear infinite;
      }
      .line8 {
        animation: line1 1.1s 1.1s linear infinite;
      }
      .line9 {
        animation: line1 1.9s 0.9s linear infinite;
      }
      .line10 {
        animation: line1 1.7s 1.3s linear infinite;
      }
      .line11 {
        animation: line1 1.3s 1.1s linear infinite;
      }
      .line12 {
        animation: line1 1.4s 0.4s linear infinite;
      }
      .annulus {
        width: 300px;
        height: 300px;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translateX(-50%) translateY(-50%);
        background: conic-gradient(
          rgb(69, 164, 254) 0,
          rgb(69, 164, 254) 2%,
          transparent 2%
        );
        border-radius: 50%;
        -webkit-mask: radial-gradient(
          transparent,
          transparent 57%,
          #000 57%,
          #000 100%
        );
      }
      .annulus1 {
        transform: translateX(-50%) translateY(-50%) rotateZ(10deg);
      }
      .annulus2 {
        transform: translateX(-50%) translateY(-50%) rotateZ(20deg);
      }
      .annulus3 {
        transform: translateX(-50%) translateY(-50%) rotateZ(30deg);
      }
      .annulus4 {
        transform: translateX(-50%) translateY(-50%) rotateZ(40deg);
      }
      .annulus5 {
        transform: translateX(-50%) translateY(-50%) rotateZ(50deg);
      }
      .annulus6 {
        transform: translateX(-50%) translateY(-50%) rotateZ(60deg);
      }
      .annulus7 {
        transform: translateX(-50%) translateY(-50%) rotateZ(70deg);
      }
      .annulus8 {
        transform: translateX(-50%) translateY(-50%) rotateZ(80deg);
      }
      .annulus9 {
        transform: translateX(-50%) translateY(-50%) rotateZ(90deg);
      }
      .annulus10 {
        transform: translateX(-50%) translateY(-50%) rotateZ(100deg);
      }
      .annulus11 {
        transform: translateX(-50%) translateY(-50%) rotateZ(110deg);
      }
      .annulus12 {
        transform: translateX(-50%) translateY(-50%) rotateZ(120deg);
      }
      .annulus13 {
        transform: translateX(-50%) translateY(-50%) rotateZ(130deg);
      }
      .annulus14 {
        transform: translateX(-50%) translateY(-50%) rotateZ(140deg);
      }
      .annulus15 {
        transform: translateX(-50%) translateY(-50%) rotateZ(150deg);
      }
      .annulus16 {
        transform: translateX(-50%) translateY(-50%) rotateZ(160deg);
      }
      .annulus17 {
        transform: translateX(-50%) translateY(-50%) rotateZ(170deg);
      }
      .annulus18 {
        transform: translateX(-50%) translateY(-50%) rotateZ(180deg);
      }
      .annulus19 {
        transform: translateX(-50%) translateY(-50%) rotateZ(190deg);
      }
      .annulus20 {
        transform: translateX(-50%) translateY(-50%) rotateZ(200deg);
      }
      .annulus21 {
        transform: translateX(-50%) translateY(-50%) rotateZ(210deg);
      }
      .annulus22 {
        transform: translateX(-50%) translateY(-50%) rotateZ(220deg);
      }
      .annulus23 {
        transform: translateX(-50%) translateY(-50%) rotateZ(230deg);
      }
      .annulus24 {
        transform: translateX(-50%) translateY(-50%) rotateZ(240deg);
      }
      .annulus25 {
        transform: translateX(-50%) translateY(-50%) rotateZ(250deg);
      }
      .annulus26 {
        transform: translateX(-50%) translateY(-50%) rotateZ(260deg);
      }
      .annulus27 {
        transform: translateX(-50%) translateY(-50%) rotateZ(270deg);
      }
      .annulus28 {
        transform: translateX(-50%) translateY(-50%) rotateZ(280deg);
      }
      .annulus29 {
        transform: translateX(-50%) translateY(-50%) rotateZ(290deg);
      }
      .annulus30 {
        transform: translateX(-50%) translateY(-50%) rotateZ(300deg);
      }
      .annulus31 {
        transform: translateX(-50%) translateY(-50%) rotateZ(310deg);
      }
      .annulus32 {
        transform: translateX(-50%) translateY(-50%) rotateZ(320deg);
      }
      .annulus33 {
        transform: translateX(-50%) translateY(-50%) rotateZ(330deg);
      }
      .annulus34 {
        transform: translateX(-50%) translateY(-50%) rotateZ(340deg);
      }
      .annulus35 {
        transform: translateX(-50%) translateY(-50%) rotateZ(350deg);
      }
      .annulus36 {
        transform: translateX(-50%) translateY(-50%) rotateZ(360deg);
      }
      @keyframes rotate1 {
        0% {
          transform: translateZ(20px) translateX(-50%) translateY(-50%)
            rotateZ(0deg);
        }
        100% {
          transform: translateZ(20px) translateX(-50%) translateY(-50%)
            rotateZ(-360deg);
        }
      }
      @keyframes rotate2 {
        0% {
          transform: translateX(-50%) translateY(-50%) translateZ(30px)
            rotateZ(0deg);
        }
        100% {
          transform: translateX(-50%) translateY(-50%) translateZ(30px)
            rotateZ(360deg);
        }
      }

      @keyframes line1 {
        0% {
          transform: translateY(-220px);
        }
        100% {
          transform: translateY(220px);
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="main1 flex">
        <div class="main2">
          <div class="firstCircle positon center"></div>
          <div class="secondCircle positon center"></div>
          <div class="thirdCircle positon center"></div>
          <div class="fourthCircle flex positon center">
            <div class="annulusContent">
              <div class="annulus annulus1"></div>
              <div class="annulus annulus2"></div>
              <div class="annulus annulus3"></div>
              <div class="annulus annulus4"></div>
              <div class="annulus annulus5"></div>
              <div class="annulus annulus6"></div>
              <div class="annulus annulus7"></div>
              <div class="annulus annulus8"></div>
              <div class="annulus annulus9"></div>
              <div class="annulus annulus10"></div>
              <div class="annulus annulus11"></div>
              <div class="annulus annulus12"></div>
              <div class="annulus annulus13"></div>
              <div class="annulus annulus14"></div>
              <div class="annulus annulus15"></div>
              <div class="annulus annulus16"></div>
              <div class="annulus annulus17"></div>
              <div class="annulus annulus18"></div>
              <div class="annulus annulus19"></div>
              <div class="annulus annulus20"></div>
              <div class="annulus annulus21"></div>
              <div class="annulus annulus22"></div>
              <div class="annulus annulus23"></div>
              <div class="annulus annulus24"></div>
              <div class="annulus annulus25"></div>
              <div class="annulus annulus26"></div>
              <div class="annulus annulus27"></div>
              <div class="annulus annulus28"></div>
              <div class="annulus annulus29"></div>
              <div class="annulus annulus30"></div>
              <div class="annulus annulus31"></div>
              <div class="annulus annulus32"></div>
              <div class="annulus annulus33"></div>
              <div class="annulus annulus34"></div>
              <div class="annulus annulus35"></div>
              <div class="annulus annulus36"></div>
            </div>
          </div>
          <div class="bar positon flex">
            <div class="line line1"></div>
            <div class="line line2"></div>
            <div class="line line3"></div>
            <div class="line line4"></div>
            <div class="line line5"></div>
            <div class="line line6"></div>
            <div class="line line7"></div>
            <div class="line line8"></div>
            <div class="line line9"></div>
            <div class="line line10"></div>
            <div class="line line11"></div>
          </div>
        </div>
      </div>
    </div>

    <script>
      var elem = document.querySelector('.main1')
      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)

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

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

本文转载于:

https://juejin.cn/post/7271070291689750582

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/930867.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WordPress使用子主题插件 Child Theme Wizard,即使主题升级也能够保留以前主题样式

修改WordPress网站样式&#xff0c;主题升级会导致自己定义设置的网站样式丢失&#xff0c;还需要重新设置&#xff0c;很繁琐工作量大&#xff0c;发现在WordPress 中有Child Theme Wizard子主题插件&#xff0c;使用Child Theme Wizard子主题插件&#xff0c;即使主题升级&am…

uni、js——点击与禁用(不可点击)、动态样式class

案例 没约满的时间可以点击进行选择&#xff0c;约满的就不能选择了。选择完之后变色变字。 核心思想就是创建一个第三方变量存起来&#xff0c;点击谁就存到第三方&#xff0c;在根据这个进行判断。 代码 <template><view class"content"><view cl…

基于JSP+Servlet+Mysql网上商城

基于JSPServletMysql网上商城 一、系统介绍二、功能展示三、其它四.获取源码 一、系统介绍 项目类型&#xff1a;Java web项目 项目名称&#xff1a;基于JSPServlet的网上商城 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java语言 前端技术&#xff1a;HTML、CSS、…

卷轴模式解析:如何实现用户留存、引流拓客

随着现代技术的不断发展和数字货币市场的日益成熟&#xff0c;越来越多的数字货币项目被推向市场。而消费者需求日益复杂&#xff0c;单一的玩法模式已经不能满足消费者追求更好购物体验的需求。电商平台需要尊重消费者的意愿&#xff0c;满足消费者的多样化需求&#xff0c;这…

vue组装模板(侧边栏+顶部+主体)--项目阶段4

目录 一、前言介绍 二、结构解析 三、页面拆分 &#xff08;一&#xff09;页面拆分 1.侧边栏页面&#xff08;固定&#xff09;--Aside.vue 2.顶部页面&#xff08;固定&#xff09;--Header.vue 3.主体页面&#xff08;不固定的&#xff09;--示例用UserView…

启动metastore服务报错

启动Metastore的时候报错&#xff1a; 简略的报错信息&#xff1a; MetaException(message:Error creating transactional connection factory)Caused by: MetaException(message:Error creating transactional connection factory)Caused by: javax.jdo.JDOFatalInternalExce…

识别图片中的文字

前言 PearOCR 是一款免费无限制网页版文字识别工具。 优点如下&#xff1a; 免费&#xff1a;完全免费&#xff0c;没有任何次数、大小限制&#xff0c;可以无限使用&#xff1b; 安全&#xff1a;全部数据本地运算&#xff0c;所有图片均不会被上传&#xff1b; 智能&#xf…

CRM的销售预测有什么用?如何操作?

销售预测对于销售团队非常重要&#xff0c;它可以估计未来一段时间内的销售量和收入&#xff0c;帮助销售人员制定基于数据的决策&#xff0c;提高销售业绩。CRM可以收集和分析销售数据&#xff0c;并进行销售预测。下面说说&#xff0c;什么是销售预测&#xff1f;CRM如何进行…

Buzz语音转文字安装使用(含Whisper模型下载)

简介&#xff1a; Transcribe and translate audio offline on your personal computer. Powered by OpenAI’s Whisper. 转录和翻译音频离线在您的个人计算机。由OpenAI的Whisper提供动力。 可以简单理解为QT的前端界面&#xff0c;python语言构建服务端&#xff0c;使用Whis…

Vant 4中的van-picker选择总是第一个的解决办法

Vant 4中的van-picker选择总是第一个的解决办法 官方demo <van-fieldv-model"fieldValue"is-linkreadonlylabel"城市"placeholder"选择城市"click"showPicker true" /> <van-popup v-model:show"showPicker" ro…

netty运行一段时间报错:java.io.IOException: 打开的文件过多

报错详细内容如下&#xff1a; java.io.IOException: 打开的文件过多at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:421)at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSo…

APP Binder客户端调用全流程分析

现在要搞明白JAVA层app调用跨进程的Service接口时&#xff0c;它的binder是怎样从Java->jni-->native--->binder驱动的这条链路&#xff1a;就是上图中的左半部分从上至下的流程。所以切入点在于&#xff0c;如app调用另一个进程的Service接口的getString&#xff08;…

Spring集成【MyBatis】和【PageHelper分页插件】整合---详细介绍

一&#xff0c;spring集成Mybatis的概念 Spring 整合 MyBatis 是将 MyBatis 数据访问框架与 Spring 框架进行集成&#xff0c;以实现更便捷的开发和管理。在集成过程中&#xff0c;Spring 提供了许多特性和功能&#xff0c;如依赖注入、声明式事务管理、AOP 等 它所带来给我们的…

安全学习DAY19_小程序信息打点

信息打点-小程序应用&解包反编译&抓包&静态分析&源码架构 文章目录 信息打点-小程序应用&解包反编译&抓包&静态分析&源码架构本节知识&思维导图本节使用到的链接&工具 小程序获取-各大平台&关键字搜索小程序-模版测试上线&源码…

如何开启esxi主机的ssh远程连接

环境&#xff1a;esxi主机&#xff0c;说明&#xff1a;esxi主机默认ssh是不开启的&#xff0c;需要人工手动启动&#xff0c;也可以设置同esxi主机一起开机启动。 1、找到esxi主机&#xff0c;点击“配置”那里&#xff0c;再点击右边的属性&#xff0c;如图所示&#xff1a; …

java属性映射使用MapStruct的坑

目录 1.实体类和映射类只加注解Data 2.将Data换成getter和setter后build 3.那么此时我把getter和setter换成lombok的getter和setter 1.实体类和映射类只加注解Data 映射关系类 这个时候运行 提示源参数中不存在 注意这个文件夹 2.将Data换成getter和setter后build package c…

Python如何进行基本的数学运算

Python进行基本的数学运算 Python是一门功能强大且易于学习的编程语言&#xff0c;它不仅可以用于开发应用程序&#xff0c;还可以用于执行各种数学运算。让我们一起来看看如何在Python中进行基本的数学运算。 加法、减法、乘法和除法 Python支持常见的加法、减法、乘法和除…

[论文分享]Pedestrian attribute recognition based on attribute correlation

Pedestrian attribute recognition based on attribute correlation 行人属性识别广泛应用于行人跟踪和行人重识别。 两项最基本的挑战&#xff1a; 多标签性质数据样本的差异性特征&#xff0c;例如类别不平衡和部分遮挡。 不同方法的示意图&#xff1a; 此项工作中&#…

Linux操作系统--常用指令(用户管理操作类)

用户的管理需要使用超级管理员(root)来进行操作 (1).useradd添加新用户 功能:给当前的操作系统添加新的用户 语法: useradd 用户名 (2).passwd设置用户新密码 功能:给当前的用户设置密码 语法: passwd用户名 (3).i