- A+
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
最近有一个需求,要我实现一个动画效果,效果如下
简单分析了一下效果,是一个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
来指定起始位置,例如45deg
或from left
.color-stop
:颜色停止点,定义渐变的颜色和位置。
这里我们把其他地方都设置为透明,只在4%的范围内设置颜色,这样会得到一个扇形。
mask
mask
是一个 CSS 属性,用于创建遮罩效果,即在元素上应用一个遮罩图像或图像源,以控制元素的可见性。它可以让你根据遮罩图像的不透明度来决定元素的哪些部分是可见的,哪些部分是隐藏的。
mask
属性有两种主要用法:
- 使用图像作为遮罩:
.masked-element { mask: url("mask-image.png"); }
这将使 .masked-element
元素的内容受到 mask-image.png
图像的遮罩影响。图像的不透明部分将允许元素内容显示,而图像的透明部分将隐藏元素内容。
- 使用线性渐变或径向渐变作为遮罩:
.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-side
、farthest-side
、closest-corner
、farthest-corner
或一个长度值。[position]
定义渐变的中心位置,可以使用关键字(如center
、top 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>