最近在工作中遇到一个水球进度条,用svg绘制几个波浪叠加动画写起来超简单,6哇~
文末分享源代码。记得点赞+关注+收藏!
border-image:
border-image CSS 属性允许在元素的边框上绘制图像。这使得绘制复杂的外观组件更加简单,也不用在某些情况下使用九宫格了。使用 border-image 时,其将会替换掉border-style 属性所设置的边框样式。
div{
width: 200px;
height: 80px;
border: 2px solid;
border-image: linear-gradient(180deg, red, orange) 1;
}
background-clip:
规定背景的绘制区域
语法:
background-clip: border-box|padding-box|content-box;
值 | 描述 |
---|---|
border-box | 背景被裁剪到边框盒 |
padding-box | 背景被裁剪到内边距框 |
content-box | 背景被裁剪到内容框 |
background-origin:
background-Origin属性指定background-position属性应该是相对位置。
注意如果背景图像background-attachment是"固定",这个属性没有任何效果。
语法:
background-origin: padding-box|border-box|content-box;
值 | 描述 |
---|---|
border-box | 背景图像边界框的相对位置 |
padding-box | 背景图像填充框的相对位置 |
content-box | 背景图像的相对位置的内容框 |
:root {
--bg: #222;
}
div {
width: 100px;
height: 100px;
border: 2px solid transparent;
background-image: linear-gradient(var(--bg), var(--bg)),
linear-gradient(180deg, red, orange);
/* 前一个为内容背景色,后面为边框渐变色 */
background-origin: border-box;
background-clip: content-box, border-box;
border-radius: 0px;
animation: 2s toBorder linear infinite alternate;
}
@keyframes toBorder {
100% {
border-radius: 50%;
}
}
SVG:可缩放矢量图形
可缩放矢量图形(Scalable Vector Graphics,SVG)基于 XML 标记语言,用于描述二维的矢量图形。
作为一个基于文本的开放网络标准,SVG 能够优雅而简洁地渲染不同大小的图形,并和CSS、DOM、JavaScript 和 SMIL 等其他网络标准无缝衔接。
本质上,SVG 相对于图像,就好比 HTML 相对于文本。和传统的点阵图像模式(如 JPEG 和 PNG)不同的是,SVG 格式提供的是矢量图,这意味着它的图像能够被无限放大而不失真或降低质量,并且可以方便地修改内容,无需图形编辑器。通过使用合适的库进行配合,SVG 文件甚至可以随时进行本地化。
兼容性:
xmlns:http://www.w3.org/2000/svg 固定值
xmlns:xlink:http://www.w3.org/1999/xlink 固定值
xml:space:preserve 固定值
path元素是 SVG基本形状中最强大的一个。你可以用它创建线条,曲线,弧形等等。
path 只需要设定很少的点,就可以创建平滑流畅的线条(比如曲线)。
虽然polyline元素也能实现类似的效果,但是必须设置大量的点(点越密集,越接近连续,看起来越平滑流畅),并且这种做法不能够放大(放大后,点的离散更明显)
path 标签用来定义路径,path 元素的形状是通过属性d定义的,属性d的值是一个“命令 + 参数”的序列
下面的命令可用于路径数据:(所有命令均可小写。大写表示绝对定位,小写表示相对定位)
M = moveto
L = lineto
H = horizontal lineto
V = vertical lineto
C = curveto
S = smooth curveto
Q = quadratic Belzier curve
T = smooth quadratic Belzier curveto
A = elliptical Arc
Z = closepath
1.在线绘制svg波浪:https://getwaves.io/
2.在线绘制svg波浪:https://fffuel.co/sssurf/
3.在线绘制svg波浪:https://svgwave.in/
在线查看svg:https://c.runoob.com/more/svgeditor/
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 600 140" class="box-waves">
<path d="M 0 70 Q 75 20,150 70 T 300 70 T 450 70 T 600 70 L 600 140 L 0 140 L 0 70Z">
</path>
</svg>
div{
fill: #a0edff;
stroke: orange;
}
svg:nth-child(1) {
fill: #a0edff;
transform: translate(-50%, 0);
z-index: 3;
animation: wave-move1 1.5s linear infinite;
}
svg:nth-child(2) {
fill: rgba(40, 187, 255, 0.5);
transform: translate(0, 0);
z-index: 2;
animation: wave-move2 3s linear infinite;
}
svg:nth-child(3) {
fill: #2084cc;
transform: translate(-50%, 0);
z-index: 1;
animation: wave-move1 3s linear infinite;
}
@keyframes wave-move1 {
100% {
transform: translate(0, 0);
}
}
@keyframes wave-move2 {
100% {
transform: translate(-50%, 0);
}
}
<div class="box-inner"></div>
.box-inner {
width: 200px;
height: 200px;
box-shadow: 0px 2px 7px 0px #238fdb;
border-radius: 50%;
position: relative;
border: 2px solid transparent;
background-image: linear-gradient(#021f40, #021f40),
linear-gradient(180deg, rgba(36, 144, 220, 0.41), rgba(37, 147, 225, 1));
background-origin: border-box;
background-clip: content-box, border-box;
/* overflow: hidden; 溢出隐藏 */
}
<div class="box-inner">
<div class="inner"></div>
</div>
.inner {
position: relative;
width: 100%;
height: 100%;
position: absolute;
left: 0;
bottom: -128%;
background-color: #a0edff;
}
bottom数值=calc(-128% + 当前百分比)
transform数值=translateY(calc(0% - 当前百分比));
<div class="inner" style="--per:50%" id="box"></div>
.inner {
width: 100%;
height: 100%;
position: absolute;
left: 0;
background-color: #a0edff;
/* 直接对bottom操作 */
bottom: calc(-128% + var(--per));
/* 或者y方向偏移
transform: translateY(calc(0% - var(--per)));*/
}
<div class="box flex-row j_c">
<div class="box-inner">
<div class="inner" style="--per:0%" id="box">
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 600 140" class="box-waves">
<path d="M 0 70 Q 75 20,150 70 T 300 70 T 450 70 T 600 70 L 600 140 L 0 140 L 0 70Z">
</path>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 600 140" class="box-waves">
<path d="M 0 70 Q 75 20,150 70 T 300 70 T 450 70 T 600 70 L 600 140 L 0 140 L 0 70Z">
</path>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 600 140" class="box-waves">
<path d="M 0 70 Q 75 20,150 70 T 300 70 T 450 70 T 600 70 L 600 140 L 0 140 L 0 70Z">
</path>
</svg>
</div>
</div>
<div id="percentText" class="box-text">--%</div>
</div>
:root {
--bg: #222;
--wave1: #a0edff;
--wave2: rgba(40, 187, 255, 0.5);
--wave3: #2084cc;
}
body {
background: var(--bg);
}
.box {
width: 650px;
height: 300px;
background: linear-gradient(270deg,
rgba(29, 170, 210, 0) 0%,
rgba(29, 170, 210, 0.1) 13%,
rgba(29, 170, 210, 0.4) 49%,
rgba(29, 170, 210, 0.1) 84%,
rgba(29, 170, 210, 0) 100%);
border: 1px solid;
border-image: linear-gradient(270deg,
rgba(81, 201, 232, 0),
rgba(56, 187, 222, 1),
rgba(30, 172, 212, 0)) 1 1;
margin-bottom: 120px;
}
.box-inner {
width: 200px;
height: 200px;
box-shadow: 0px 2px 7px 0px #238fdb;
border-radius: 50%;
position: relative;
border: 2px solid transparent;
background-image: linear-gradient(#021f40, #021f40),
linear-gradient(180deg, rgba(36, 144, 220, 0.41), rgba(37, 147, 225, 1));
background-origin: border-box;
background-clip: content-box, border-box;
overflow: hidden;
}
.inner {
width: 100%;
height: 100%;
position: absolute;
left: 0;
background: #a0edff;
/* 直接对bottom操作 */
bottom: calc(-128% + var(--per));
}
.box-waves {
position: absolute;
left: 0;
bottom: 100%;
width: 200%;
stroke: none;
}
.box-waves:nth-child(1) {
fill: var(--wave1);
transform: translate(-50%, 0);
z-index: 3;
animation: wave-move1 1.5s linear infinite;
/* svg重合有一条线 */
margin-bottom: -2px;
}
.box-waves:nth-child(2) {
fill: var(--wave2);
transform: translate(0, 0);
z-index: 2;
animation: wave-move2 3s linear infinite;
}
.box-waves:nth-child(3) {
fill: var(--wave3);
transform: translate(-50%, 0);
z-index: 1;
animation: wave-move1 3s linear infinite;
}
@keyframes wave-move1 {
100% {
transform: translate(0, 0);
}
}
@keyframes wave-move2 {
100% {
transform: translate(-50%, 0);
}
}
.box-text {
font-size: 30px;
font-weight: bold;
width: 80px;
margin-left: 20px;
text-align: center;
color: #7EEDFF;
}
const getData = () => {
const box = document.getElementById('box');
const text = document.getElementById('percentText');
let i = 0;
let timer = null;
const loading = () => {
if (i < 100) {
i++;
box.style.setProperty('--per', i + '%'); // 设置CSS变量
text.innerHTML = i + '%';
} else {
i = 0;
clearInterval(timer);
setTimeout(() => {
text.innerHTML = '0%';
box.style.setProperty('--per', '0%'); // 设置CSS变量
timer = setInterval(loading, 1000);
}, 2000);
}
}
loading();
timer = setInterval(loading, 1000);
}
getData();