如何通过CSS ::before伪元素实现0-360度旋转渐变覆盖动画?
问题定义
我有一个设置了border-radius: 50%的div标签,用来显示圆形,相关代码如下:
.pie-wrapper { height: 2.5em; width: 2.5em; margin: 15px auto; position: relative; } .pie-wrapper--solid { border-radius: 50%; overflow: hidden; } .pie-wrapper--solid:before { border-radius: 0 100% 100% 0 / 50%; content: ""; display: block; height: 100%; margin-left: 50%; transform-origin: left; } .pie-wrapper--solid.progress-88 { border: 5px ridge blue; background: linear-gradient(to right, springgreen 50%, #ff0000 50%); } .pie-wrapper--solid.progress-88:before { background: springgreen; transform: rotate(0deg); animation-name: change-color; animation-duration: 5s; animation-timing-function: linear; animation-fill-mode: forwards; animation-iteration-count: 1; animation-direction: normal; } /* Keyframes */ @keyframes change-color { 0% { transform: rotate(0deg); } 100% { transform: rotate(180deg); } }
<div class="pie-wrapper pie-wrapper--solid progress-88"> </div>
已尝试方案
我用linear-gradient创建了双色背景,还试过to left、to bottom、to top等不同的渐变方向,但都没达到预期效果。
期望效果
当前动画可以正常旋转到180度,但旋转角度超过180度时,没法按预期覆盖饼图区域。我的目标是在keyframes里设置rotate(360deg),让红色部分完全覆盖绿色部分,形成完整的红色圆形;同时希望动画可以逆时针旋转(可以通过rotate函数里的负值实现)。
解决方案
当前的实现仅靠单个伪元素旋转无法支持超过180度的完整覆盖,因为伪元素仅占容器右半部分。可以通过调整背景色切换和伪元素的动画逻辑来实现需求:
顺时针实现(最终全红)
修改后的CSS代码如下:
.pie-wrapper { height: 2.5em; width: 2.5em; margin: 15px auto; position: relative; } .pie-wrapper--solid { border-radius: 50%; overflow: hidden; border: 5px ridge blue; /* 初始背景:左绿右红 */ background: linear-gradient(to right, springgreen 50%, #ff0000 50%); } .pie-wrapper--solid:before { border-radius: 0 100% 100% 0 / 50%; content: ""; display: block; height: 100%; margin-left: 50%; transform-origin: left; background: springgreen; transform: rotate(0deg); animation-name: fill-red; animation-duration: 5s; animation-timing-function: linear; animation-fill-mode: forwards; } @keyframes fill-red { 0% { transform: rotate(0deg); background: springgreen; } /* 旋转180度时,伪元素完全覆盖左半绿色,此时整体全红 */ 50% { transform: rotate(180deg); background: springgreen; } /* 切换伪元素颜色为红色,避免后续旋转露出绿色 */ 50.1% { background: #ff0000; } /* 继续旋转到360度,保持全红状态 */ 100% { transform: rotate(360deg); background: #ff0000; } }
逆时针实现(最终全红)
添加反向动画的CSS代码:
.pie-wrapper--solid.reverse:before { animation-name: fill-red-reverse; } @keyframes fill-red-reverse { 0% { transform: rotate(0deg); background: springgreen; } 50% { transform: rotate(-180deg); background: springgreen; } 50.1% { background: #ff0000; } 100% { transform: rotate(-360deg); background: #ff0000; } }
对应的HTML使用方式:
<!-- 顺时针版本 --> <div class="pie-wrapper pie-wrapper--solid progress-88"></div> <!-- 逆时针版本 --> <div class="pie-wrapper pie-wrapper--solid progress-88 reverse"></div>
逻辑说明
- 0-50%动画阶段:伪元素旋转180度(顺时针/逆时针),逐步覆盖容器左半部分的绿色,到50%节点时完全覆盖,整体呈现全红色。
- 50.1%-100%阶段:将伪元素颜色切换为红色,继续旋转至360度,确保动画结束后保持全红色,不会因伪元素回转而露出绿色。
内容的提问来源于stack exchange,提问作者Tawanda Andrew Msengezi
相关产品推荐
相关产品推荐

