Кевин Asked:2020-01-13 04:30:40 +0000 UTC2020-01-13 04:30:40 +0000 UTC 2020-01-13 04:30:40 +0000 UTC 如何制作圆形进度条并使用 CSS 对其进行动画处理 772 有一个带框的圆圈: 框架的长度需要逐渐减小(像进度条一样),但通常的border没有长度参数,只有宽度。 我认为一个标签可能适合这个<hr>,它的长度和宽度都可以减少,但我不知道如何使它弯曲。 不,当然这可以使用 SVG 或 来完成canvas,但我对 HTML、CSS 中的实现很感兴趣。 对此有什么想法吗? html 3 个回答 Voted Best Answer user355286 2020-01-13T04:49:20Z2020-01-13T04:49:20Z body { margin: 0; height: 100vh; display: flex; align-items: center; justify-content: center; } .circle { width: 200px; height: 200px; border-radius: 50%; display: flex; align-items: center; justify-content: center; position: relative; } .circle>div { width: 100%; height: 100%; position: absolute; border-radius: 50%; } .outer { background-color: #03A9F4; clip-path: polygon(50% 0%, 100% 0, 100% 100%, 0 100%, 0 100%, 0 0, 50% 0, 50% 50%, 50% 50%); } .inner { transform: scale(0.95); background-color: #E0E0E0; } .circle:hover .outer { animation: xxx 2s linear forwards; } @keyframes xxx { 12.5% { clip-path: polygon(50% 0%, 100% 0, 100% 100%, 0 100%, 0 100%, 0 0, 0 0, 50% 50%, 50% 50%); } 25% { clip-path: polygon(50% 0%, 100% 0, 100% 100%, 0 100%, 0 100%, 0 50%, 0 50%, 50% 50%, 50% 50%); } 37.5% { clip-path: polygon(50% 0%, 100% 0, 100% 100%, 0 100%, 0 100%, 0 100%, 0 100%, 50% 50%, 50% 50%); } 50% { clip-path: polygon(50% 0%, 100% 0, 100% 100%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 50% 50%, 50% 50%); } 62.5% { clip-path: polygon(50% 0%, 100% 0, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 50% 50%, 50% 50%); } 75% { clip-path: polygon(50% 0%, 100% 0, 100% 50%, 100% 50%, 100% 50%, 100% 50%, 100% 50%, 50% 50%, 50% 50%); } 87.5% { clip-path: polygon(50% 0%, 100% 0, 100% 0, 100% 0, 100% 0, 100% 0, 100% 0, 50% 50%, 50% 50%); } 100% { clip-path: polygon(50% 0%, 50% 0, 50% 0, 50% 0, 50% 0, 50% 0, 50% 0, 50% 50%, 50% 50%); } } <div class="circle"> <div class="outer"></div> <div class="inner"></div> </div> 你可以看到它是如何切割的: body { margin: 0; height: 100vh; display: flex; align-items: center; justify-content: center; } .circle { width: 200px; height: 200px; border-radius: 50%; display: flex; align-items: center; justify-content: center; position: relative; } .circle > div { width: 100%; height: 100%; position: absolute; } .outer { background-color: #03A9F4; clip-path: polygon(50% 0, 100% 0, 100% 100%, 0 100%, 0 0, 50% 0, 50% 50%); } .inner { transform: scale(0.95); background-color: #E0E0E0; opacity: 0.5; } .circle:hover .outer { animation: xxx 2s linear forwards; } @keyframes xxx { 12.5% { clip-path: polygon(50% 0, 100% 0, 100% 100%, 0 100%, 0 0, 0 0, 50% 50%); } 25% { clip-path: polygon(50% 0, 100% 0, 100% 100%, 0 100%, 0 50%, 0 50%, 50% 50%); } 37.5% { clip-path: polygon(50% 0, 100% 0, 100% 100%, 0 100%, 0 100%, 0 100%, 50% 50%); } 50% { clip-path: polygon(50% 0, 100% 0, 100% 100%, 50% 100%, 50% 100%, 50% 100%, 50% 50%); } 62.5% { clip-path: polygon(50% 0, 100% 0, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 50% 50%); } 75% { clip-path: polygon(50% 0, 100% 0, 100% 50%, 100% 50%, 100% 50%, 100% 50%, 50% 50%); } 87.5% { clip-path: polygon(50% 0, 100% 0, 100% 0, 100% 0, 100% 0, 100% 0, 50% 50%); } 100% { clip-path: polygon(50% 0, 50% 0, 50% 0, 50% 0, 50% 0, 50% 0, 50% 50%); } } <div class="circle"> <div class="outer"></div> <div class="inner"></div> </div> Alexandr_TT 2020-01-13T18:06:22Z2020-01-13T18:06:22Z 但是为什么需要一个纯 CSS 的解决方案呢? SVG 正是为实现图形而存在,完美支持 CSS 的所有规则。 另一方面,这个 CSS 不能做 SVG 能做的所有事情。 如果使用 SVG 有困难,那么您可以在矢量编辑器中创建一个 SVG 图形,只需单击几下,复制path它,然后将所有动画传输到 CSS。 明星的动画示例,见话题底部。 比较代码变得更短和更清晰的程度。 标记在任何地方都是相同的,您只需要准确知道形状的 svg 轮廓的全长并设置适当的参数stroke-dasharray stroke-dashoffset 第一行擦除示例 通过stroke-dashoffset从零增加到最大值来实现628px 灰色方块显示 SVG 画布的边框,蓝色矩形是 SVG 的容器。 .circle { position:relative; width:215px; height:250px; background:#CDE9FF; } .svg1 { position:absolute; top:0; left:0; right:0; bottom:0; } #circ { fill:#E0E0E0; stroke:#03A9F4; stroke-width:6; stroke-dasharray:628; stroke-dashoffset:0; } #circ:hover { animation: progress 2s linear forwards; } @keyframes progress { 100% {stroke-dashoffset:628;} } <div class="circle"> <svg class="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="210" height="210" viewBox="0 0 210 210" style="border:1px solid gray" > <circle id="circ" transform="rotate(-90 105 105)" cx="105" cy="105" r="100" /> </svg> </div> 第二个例子stroke-dasharray .circle { position:relative; width:215px; height:250px; background:#CDE9FF; } .svg1 { position:absolute; top:0; left:0; right:0; bottom:0; } #circ { fill:#E0E0E0; stroke:purple; stroke-width:6; stroke-dasharray:628,0; stroke-dashoffset:-628; } #circ:hover { animation: progress 2s linear forwards; } @keyframes progress { 100% {stroke-dasharray:0,628;} } <div class="circle"> <svg class="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="210" height="210" viewBox="0 0 210 210" style="border:1px solid gray" > <circle id="circ" transform="rotate(-90 105 105)" cx="105" cy="105" r="100" /> </svg> </div> 第三个例子是两行擦除的动画 仅更改属性stroke-dasharray .circle { position:relative; width:215px; height:250px; background:#CDE9FF; } .svg1 { position:absolute; top:0; left:0; right:0; bottom:0; } #circ { fill:#E0E0E0; stroke:purple; stroke-width:6; stroke-dasharray:314,0 314,0; stroke-dashoffset:-157; } #circ:hover { animation: progress 2s linear forwards; } @keyframes progress { 100% {stroke-dasharray:0,314 0,314;} } <div class="circle"> <svg class="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="210" height="210" viewBox="0 0 210 210" style="border:1px solid gray" > <circle id="circ" transform="rotate(-90 105 105)" cx="105" cy="105" r="100" /> </svg> </div> 反之亦然,从一个点用两条线绘制 为此,您只需要交换参数stroke-dasharray .circle { position:relative; width:215px; height:250px; background:#CDE9FF; } .svg1 { position:absolute; top:0; left:0; right:0; bottom:0; } #circ { fill:#E0E0E0; stroke:purple; stroke-width:6; stroke-dasharray:0,314 0,314; stroke-dashoffset:314; } #circ:hover { animation: progress 2s linear forwards; } @keyframes progress { 100% {stroke-dasharray:0,0 628,0;} } <div class="circle"> <svg class="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="210" height="210" viewBox="0 0 210 210" style="border:1px solid gray" > <circle id="circ" transform="rotate(-90 105 105)" cx="105" cy="105" r="100" /> </svg> </div> 从单个点绘制六边形边的动画 .circle { position:relative; width:215px; height:250px; background:#CDE9FF; } .svg1 { position:absolute; top:0; left:0; right:0; bottom:0; } #hex { fill:#E0E0E0; stroke:purple; stroke-width:6; stroke-dasharray:0,300 0,300; stroke-dashoffset:300; } #hex:hover { animation: progress 2s linear forwards; } @keyframes progress { 100% {stroke-dasharray:0,0 600,0;} } <div class="circle"> <svg class="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="210" height="210" viewBox="0 0 210 210" style="border:1px solid gray" > <path id="hex" d="m105 5 86.6 50 0 100L105 205 18.4 155l0-100z"/> </svg> </div> 星光动画 .circle { position:relative; width:215px; height:250px; background:#CDE9FF; } .svg1 { position:absolute; top:0; left:0; right:0; bottom:0; } #star { fill:#E0E0E0; stroke:purple; stroke-width:6; stroke-dasharray:0,332 0,332; stroke-dashoffset:332; } #star:hover { animation: progress 2s linear forwards; } @keyframes progress { 100% {stroke-dasharray:0,0 664,0;} } <div class="circle"> <svg class="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="210" height="210" viewBox="0 0 210 210" style="border:1px solid gray" > <path id="star" d="m105 5 29.4 59.5 65.7 9.5-47.6 46.4 11.2 65.5L105 155 46.2 185.9 57.4 120.5 9.9 74.1 75.6 64.5Z"/> </svg> </div> Сергей Мишин 2020-01-13T17:16:07Z2020-01-13T17:16:07Z .progress-bar-wrapper { position: relative; display: block; height: 100px; } .center-circle { width: 60px; height: 60px; position: absolute; border-radius: 50%; background: grey; transform: translate3d(15px, 15px, 0); z-index: 3; } .sector { width: 72px; height: 72px; position: absolute; border-radius: 50%; transform: translate3d(7px, 7px, 0); z-index: 2; display: block; background-color: green; border: 2px solid green; background-image: linear-gradient(108deg, transparent 50%, white 50%), linear-gradient(90deg, white 50%, transparent 50%); animation: background 2s infinite; } @keyframes background { 15% { background-image: linear-gradient(126deg, transparent 50%, white 50%), linear-gradient(90deg, white 50%, transparent 50%); } 25% { background-image: linear-gradient(180deg, transparent 50%, white 50%), linear-gradient(90deg, white 50%, transparent 50%); } 50% { background-image: linear-gradient(90deg, white 50%, transparent 50%); } 75% { background-image: linear-gradient(180deg, transparent 50%, green 50%), linear-gradient(90deg, white 50%, transparent 50%); } 100% { background-image: none; } } <div class="progress-bar-wrapper"> <div class="center-circle"></div> <div class="sector"></div> </div> /* 10% = 126deg = 90 + ( 360 * .1 ) */ 如果要将值更改 1,则必须 background-image: linear-gradient在每帧中将值从 90 更改为 450。
你可以看到它是如何切割的:
但是为什么需要一个纯 CSS 的解决方案呢?
SVG 正是为实现图形而存在,完美支持 CSS 的所有规则。
另一方面,这个 CSS 不能做 SVG 能做的所有事情。
如果使用 SVG 有困难,那么您可以在矢量编辑器中创建一个 SVG 图形,只需单击几下,复制
path它,然后将所有动画传输到 CSS。明星的动画示例,见话题底部。
比较代码变得更短和更清晰的程度。
标记在任何地方都是相同的,您只需要准确知道形状的 svg 轮廓的全长并设置适当的参数
stroke-dasharraystroke-dashoffset第一行擦除示例
通过
stroke-dashoffset从零增加到最大值来实现628px灰色方块显示 SVG 画布的边框,蓝色矩形是 SVG 的容器。
第二个例子
stroke-dasharray第三个例子是两行擦除的动画
仅更改属性
stroke-dasharray反之亦然,从一个点用两条线绘制
为此,您只需要交换参数
stroke-dasharray从单个点绘制六边形边的动画
星光动画
如果要将值更改 1,则必须
background-image: linear-gradient在每帧中将值从 90 更改为 450。