我想用 CSS3 或 JavaScript 创建一个环形进程微调器,类似于 Android 中的加载进度微调器。
微调器应连续旋转并填充沿边缘淡出的纯色(即圆锥形渐变),如下图所示:
我怎样才能做到这一点?
最佳答案
如果只有 CSS 或 SVG 具有锥形渐变,这将非常容易!直到 conic-gradient()
notation成熟并获得支持,我们可以通过切割渐变并以某种方式覆盖接缝来近似效果。
您将在下面找到两个解决方案。第一个解决方案使用嵌入式 SVG 图像;第二种使用多个 CSS 渐变和伪元素。
两者都以单个 div
开始,应用关键帧动画使其旋转:
HTML:
<div class="spinner"></div>
CSS:
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.spinner {
animation: rotate 1s linear infinite;
height: 200px;
width: 200px;
}
如果您愿意,可以使用 progress
元素,但您会发现设计样式很麻烦。另请注意,除非您使用 prefixfree.js 之类的东西,否则您需要添加供应商前缀版本的 @keyframes
at-rule 和 transform
和 animation
属性。
SVG 解决方案
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.spinner {
animation: rotate 1s linear infinite;
background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwLDAgMjAwLDIwMCI+PGRlZnM+PGNsaXBQYXRoIGlkPSJyaW5nIj48cGF0aCBkPSJNMjAwLDEwMEExMDAsMTAwLDAsMSwxLDE5Ny44MSw3OS4yMUwxODguMDMsODEuMjlBOTAsOTAsMCwxLDAsMTkwLDEwMHoiLz48L2NsaXBQYXRoPjxmaWx0ZXIgaWQ9ImJsdXIiIHg9IjAiIHk9IjAiPjxmZUdhdXNzaWFuQmx1ciBpbj0iU291cmNlR3JhcGhpYyIgc3RkRGV2aWF0aW9uPSIzIiAvPjwvZmlsdGVyPjxwYXRoIGlkPSJwIiBkPSJNMjUwLDEwMEExNTAsMTUwLDAsMCwxLDI0Ni43MiwxMzEuMTlMMTAwLDEwMEEwLDAsMCwwLDAsMTAwLDEwMHoiIGZpbGw9ImN5YW4iLz48L2RlZnM+PGcgY2xpcC1wYXRoPSJ1cmwoI3JpbmcpIj48ZyBmaWx0ZXI9InVybCgjYmx1cikiIHRyYW5zZm9ybT0icm90YXRlKC02IDEwMCAxMDApIj48dXNlIHhsaW5rOmhyZWY9IiNwIiBmaWxsLW9wYWNpdHk9IjAiIHRyYW5zZm9ybT0icm90YXRlKDAgMTAwIDEwMCkiLz48dXNlIHhsaW5rOmhyZWY9IiNwIiBmaWxsLW9wYWNpdHk9Ii4wMyIgdHJhbnNmb3JtPSJyb3RhdGUoMTIgMTAwIDEwMCkiLz48dXNlIHhsaW5rOmhyZWY9IiNwIiBmaWxsLW9wYWNpdHk9Ii4wNyIgdHJhbnNmb3JtPSJyb3RhdGUoMjQgMTAwIDEwMCkiLz48dXNlIHhsaW5rOmhyZWY9IiNwIiBmaWxsLW9wYWNpdHk9Ii4xIiB0cmFuc2Zvcm09InJvdGF0ZSgzNiAxMDAgMTAwKSIvPjx1c2UgeGxpbms6aHJlZj0iI3AiIGZpbGwtb3BhY2l0eT0iLjE0IiB0cmFuc2Zvcm09InJvdGF0ZSg0OCAxMDAgMTAwKSIvPjx1c2UgeGxpbms6aHJlZj0iI3AiIGZpbGwtb3BhY2l0eT0iLjE3IiB0cmFuc2Zvcm09InJvdGF0ZSg2MCAxMDAgMTAwKSIvPjx1c2UgeGxpbms6aHJlZj0iI3AiIGZpbGwtb3BhY2l0eT0iLjIiIHRyYW5zZm9ybT0icm90YXRlKDcyIDEwMCAxMDApIi8+PHVzZSB4bGluazpocmVmPSIjcCIgZmlsbC1vcGFjaXR5PSIuMjQiIHRyYW5zZm9ybT0icm90YXRlKDg0IDEwMCAxMDApIi8+PHVzZSB4bGluazpocmVmPSIjcCIgZmlsbC1vcGFjaXR5PSIuMjgiIHRyYW5zZm9ybT0icm90YXRlKDk2IDEwMCAxMDApIi8+PHVzZSB4bGluazpocmVmPSIjcCIgZmlsbC1vcGFjaXR5PSIuMzEiIHRyYW5zZm9ybT0icm90YXRlKDEwOCAxMDAgMTAwKSIvPjx1c2UgeGxpbms6aHJlZj0iI3AiIGZpbGwtb3BhY2l0eT0iLjM0IiB0cmFuc2Zvcm09InJvdGF0ZSgxMjAgMTAwIDEwMCkiLz48dXNlIHhsaW5rOmhyZWY9IiNwIiBmaWxsLW9wYWNpdHk9Ii4zOCIgdHJhbnNmb3JtPSJyb3RhdGUoMTMyIDEwMCAxMDApIi8+PHVzZSB4bGluazpocmVmPSIjcCIgZmlsbC1vcGFjaXR5PSIuNDEiIHRyYW5zZm9ybT0icm90YXRlKDE0NCAxMDAgMTAwKSIvPjx1c2UgeGxpbms6aHJlZj0iI3AiIGZpbGwtb3BhY2l0eT0iLjQ1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTYgMTAwIDEwMCkiLz48dXNlIHhsaW5rOmhyZWY9IiNwIiBmaWxsLW9wYWNpdHk9Ii40OCIgdHJhbnNmb3JtPSJyb3RhdGUoMTY4IDEwMCAxMDApIi8+PHVzZSB4bGluazpocmVmPSIjcCIgZmlsbC1vcGFjaXR5PSIuNTIiIHRyYW5zZm9ybT0icm90YXRlKDE4MCAxMDAgMTAwKSIvPjx1c2UgeGxpbms6aHJlZj0iI3AiIGZpbGwtb3BhY2l0eT0iLjU1IiB0cmFuc2Zvcm09InJvdGF0ZSgxOTIgMTAwIDEwMCkiLz48dXNlIHhsaW5rOmhyZWY9IiNwIiBmaWxsLW9wYWNpdHk9Ii41OSIgdHJhbnNmb3JtPSJyb3RhdGUoMjA0IDEwMCAxMDApIi8+PHVzZSB4bGluazpocmVmPSIjcCIgZmlsbC1vcGFjaXR5PSIuNjIiIHRyYW5zZm9ybT0icm90YXRlKDIxNiAxMDAgMTAwKSIvPjx1c2UgeGxpbms6aHJlZj0iI3AiIGZpbGwtb3BhY2l0eT0iLjY2IiB0cmFuc2Zvcm09InJvdGF0ZSgyMjggMTAwIDEwMCkiLz48dXNlIHhsaW5rOmhyZWY9IiNwIiBmaWxsLW9wYWNpdHk9Ii42OSIgdHJhbnNmb3JtPSJyb3RhdGUoMjQwIDEwMCAxMDApIi8+PHVzZSB4bGluazpocmVmPSIjcCIgZmlsbC1vcGFjaXR5PSIuNyIgdHJhbnNmb3JtPSJyb3RhdGUoMjUyIDEwMCAxMDApIi8+PHVzZSB4bGluazpocmVmPSIjcCIgZmlsbC1vcGFjaXR5PSIuNzIiIHRyYW5zZm9ybT0icm90YXRlKDI2NCAxMDAgMTAwKSIvPjx1c2UgeGxpbms6aHJlZj0iI3AiIGZpbGwtb3BhY2l0eT0iLjc2IiB0cmFuc2Zvcm09InJvdGF0ZSgyNzYgMTAwIDEwMCkiLz48dXNlIHhsaW5rOmhyZWY9IiNwIiBmaWxsLW9wYWNpdHk9Ii43OSIgdHJhbnNmb3JtPSJyb3RhdGUoMjg4IDEwMCAxMDApIi8+PHVzZSB4bGluazpocmVmPSIjcCIgZmlsbC1vcGFjaXR5PSIuODMiIHRyYW5zZm9ybT0icm90YXRlKDMwMCAxMDAgMTAwKSIvPjx1c2UgeGxpbms6aHJlZj0iI3AiIGZpbGwtb3BhY2l0eT0iLjg2IiB0cmFuc2Zvcm09InJvdGF0ZSgzMTIgMTAwIDEwMCkiLz48dXNlIHhsaW5rOmhyZWY9IiNwIiBmaWxsLW9wYWNpdHk9Ii45MyIgdHJhbnNmb3JtPSJyb3RhdGUoMzI0IDEwMCAxMDApIi8+PHVzZSB4bGluazpocmVmPSIjcCIgZmlsbC1vcGFjaXR5PSIuOTciIHRyYW5zZm9ybT0icm90YXRlKDMzNiAxMDAgMTAwKSIvPjx1c2UgeGxpbms6aHJlZj0iI3AiIGZpbGwtb3BhY2l0eT0iMSIgdHJhbnNmb3JtPSJyb3RhdGUoMzQ4IDEwMCAxMDApIi8+PC9nPjwvZz48L3N2Zz4=') no-repeat;
height: 200px;
width: 200px;
}
<div class="spinner"></div>
在 IE 10、Chrome 和 Firefox 中测试并工作。
注意事项
更改环的内半径或外半径比您想象的要痛苦得多,因为这需要编辑剪辑路径值。解释如何计算它超出了这个答案的范围,但足以说明它需要一些几何知识。如果有时间,我会尝试在 GitHub 上放一个生成器。
SVG 版本的工作原理
那一大堆乱码只是一个 Base64 编码的 SVG 图像。通过 a Base64 decoder 运行它你会看到原始的 SVG 图像。
这是完整的图像,缩进和注释很好,因此您可以确切地看到它是如何工作的:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0 200,200">
<defs>
<!-- Ring shape centred on 100, 100 with inner radius 90px, outer
radius 100px and a 12 degree gap at 348. -->
<clipPath id="ring">
<path d="M 200, 100
A 100, 100, 0, 1, 1, 197.81, 79.21
L 188.03, 81.29
A 90, 90, 0, 1, 0, 190, 100 z"/>
</clipPath>
<!-- Very simple Gaussian blur, used to visually merge sectors. -->
<filter id="blur" x="0" y="0">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
<!-- A 12 degree sector extending to 150px. -->
<path id="p" d="M 250, 100
A 150, 150, 0, 0, 1, 246.72, 131.19
L 100, 100
A 0, 0, 0, 0, 0, 100, 100 z" fill="cyan"/>
</defs>
<!-- Clip the blurred sectors to the ring shape. -->
<g clip-path="url(#ring)">
<!-- Blur the sectors together to make a smooth shape and rotate
them anti-clockwise by 6 degrees to hide the seam where the
fully opaque sector blurs with the fully transparent one. -->
<g filter="url(#blur)" transform="rotate(-6 100 100)">
<!-- Each successive sector increases in opacity and is rotated
by a further 12 degrees. -->
<use xlink:href="#p" fill-opacity="0" transform="rotate( 0 100 100)"/>
<use xlink:href="#p" fill-opacity="0.03" transform="rotate( 12 100 100)"/>
<use xlink:href="#p" fill-opacity="0.07" transform="rotate( 24 100 100)"/>
<use xlink:href="#p" fill-opacity="0.1" transform="rotate( 36 100 100)"/>
<use xlink:href="#p" fill-opacity="0.14" transform="rotate( 48 100 100)"/>
<use xlink:href="#p" fill-opacity="0.17" transform="rotate( 60 100 100)"/>
<use xlink:href="#p" fill-opacity="0.2" transform="rotate( 72 100 100)"/>
<use xlink:href="#p" fill-opacity="0.24" transform="rotate( 84 100 100)"/>
<use xlink:href="#p" fill-opacity="0.28" transform="rotate( 96 100 100)"/>
<use xlink:href="#p" fill-opacity="0.31" transform="rotate(108 100 100)"/>
<use xlink:href="#p" fill-opacity="0.34" transform="rotate(120 100 100)"/>
<use xlink:href="#p" fill-opacity="0.38" transform="rotate(132 100 100)"/>
<use xlink:href="#p" fill-opacity="0.41" transform="rotate(144 100 100)"/>
<use xlink:href="#p" fill-opacity="0.45" transform="rotate(156 100 100)"/>
<use xlink:href="#p" fill-opacity="0.48" transform="rotate(168 100 100)"/>
<use xlink:href="#p" fill-opacity="0.52" transform="rotate(180 100 100)"/>
<use xlink:href="#p" fill-opacity="0.55" transform="rotate(192 100 100)"/>
<use xlink:href="#p" fill-opacity="0.59" transform="rotate(204 100 100)"/>
<use xlink:href="#p" fill-opacity="0.62" transform="rotate(216 100 100)"/>
<use xlink:href="#p" fill-opacity="0.66" transform="rotate(228 100 100)"/>
<use xlink:href="#p" fill-opacity="0.69" transform="rotate(240 100 100)"/>
<use xlink:href="#p" fill-opacity="0.7" transform="rotate(252 100 100)"/>
<use xlink:href="#p" fill-opacity="0.72" transform="rotate(264 100 100)"/>
<use xlink:href="#p" fill-opacity="0.76" transform="rotate(276 100 100)"/>
<use xlink:href="#p" fill-opacity="0.79" transform="rotate(288 100 100)"/>
<use xlink:href="#p" fill-opacity="0.83" transform="rotate(300 100 100)"/>
<use xlink:href="#p" fill-opacity="0.86" transform="rotate(312 100 100)"/>
<use xlink:href="#p" fill-opacity="0.93" transform="rotate(324 100 100)"/>
<use xlink:href="#p" fill-opacity="0.97" transform="rotate(336 100 100)"/>
<use xlink:href="#p" fill-opacity="1" transform="rotate(348 100 100)"/>
</g>
</g>
</svg>
这是缩小的,Base64 encoded并用作内联 CSS 背景图像。如果您愿意,也可以将其作为单独的文件提供。从技术上讲,应该可以在没有 Base64 编码的情况下嵌入图像,但目前只能在 Chrome 中使用。
纯 CSS 解决方案
此解决方案在每个象限中使用单独的线性渐变,并依靠视觉相似性来掩盖接缝。环形是使用伪元素形成的。
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.spinner {
animation: rotate 1s linear infinite;
background: cyan;
border-radius: 50%;
height: 200px;
width: 200px;
position: relative;
}
.spinner::before,
.spinner::after {
content: '';
position: absolute;
}
.spinner::before {
border-radius: 50%;
background:
linear-gradient(0deg, hsla(0, 0%, 100%, 1 ) 50%, hsla(0, 0%, 100%, 0.9) 100%) 0% 0%,
linear-gradient(90deg, hsla(0, 0%, 100%, 0.9) 0%, hsla(0, 0%, 100%, 0.6) 100%) 100% 0%,
linear-gradient(180deg, hsla(0, 0%, 100%, 0.6) 0%, hsla(0, 0%, 100%, 0.3) 100%) 100% 100%,
linear-gradient(360deg, hsla(0, 0%, 100%, 0.3) 0%, hsla(0, 0%, 100%, 0 ) 100%) 0% 100%
;
background-repeat: no-repeat;
background-size: 50% 50%;
top: -1px;
bottom: -1px;
left: -1px;
right: -1px;
}
.spinner::after {
background: white;
border-radius: 50%;
top: 3%;
bottom: 3%;
left: 3%;
right: 3%;
}
<div class="spinner"></div>
在 IE 10、Chrome 和 Firefox 中测试并工作。
注意事项
与 SVG 解决方案不同,这仅适用于纯色背景。如果你想改变那种颜色,它还需要在几个地方进行修改,这很痛苦。
纯 CSS 版本的工作原理
首先,微调器的样式设置为具有统一背景色的圆圈。这将是旋转渐变的颜色。
.spinner { background: cyan; border-radius: 50%; /* ... */ }
进行设置,以便我们可以将伪元素叠加在微调器的顶部:
.spinner { /* ... */ position: relative; } .spinner::before, .spinner::after { content: ''; position: absolute; }
这是棘手的一点。
:before
伪元素的每个象限都设置为不同的线性渐变,从不透明的白色开始,逐渐变得越来越透明。朝向中心很容易看到渐变连接的位置,但请注意在外部周围颜色如何靠得足够近,以至于它们看起来平滑地连接在一起。.spinner::before { border-radius: 50%; background: linear-gradient(0deg, hsla(0, 0%, 100%, 1 ) 50%, hsla(0, 0%, 100%, 0.9) 100%) 0% 0%, linear-gradient(90deg, hsla(0, 0%, 100%, 0.9) 0%, hsla(0, 0%, 100%, 0.6) 100%) 100% 0%, linear-gradient(180deg, hsla(0, 0%, 100%, 0.6) 0%, hsla(0, 0%, 100%, 0.3) 100%) 100% 100%, linear-gradient(360deg, hsla(0, 0%, 100%, 0.3) 0%, hsla(0, 0%, 100%, 0 ) 100%) 0% 100% ; background-repeat: no-repeat; background-size: 50% 50%; top: -1px; bottom: -1px; left: -1px; right: -1px; }
它的位置使其稍微越过微调器的边缘,因为如果我们将它放置在边缘的右边,背景颜色的微弱边缘是可见的。
最后,使用
::after
伪元素隐藏中间位以形成环形:.spinner::after { background: white; border-radius: 50%; top: 3%; bottom: 3%; left: 3%; right: 3%; }
Et voilá!
关于html - 环形工艺微调器,在环周围具有渐变渐变效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49520226/