如何为JS Fiddle环形进度条添加箭头形状
如何给环形进度条末端添加箭头形状?
我完全理解你想给这个环形进度条的末端加上箭头的需求,其实我们可以通过新增一个箭头元素,配合CSS的定位、旋转动画来实现,刚好能和现有进度条的动画完美同步。下面是具体的修改步骤和完整代码:
步骤1:修改HTML结构
首先在你的.progress容器里新增一个用于显示箭头的元素,放在进度值元素后面即可:
<div class="progress blue" style="margin-top:50px;"> <span class="progress-left"> <span class="progress-bar"></span> </span> <span class="progress-right"> <span class="progress-bar"></span> </span> <div class="progress-value">90%</div> <div class="progress-arrow"></div> <!-- 新增箭头元素 --> </div>
步骤2:添加箭头的CSS样式
我们用CSS边框来绘制三角形箭头,然后通过绝对定位和旋转动画让它跟随进度条的末端移动:
/* 箭头基础样式 */ .progress-arrow { position: absolute; top: -6px; /* 调整这个值让箭头和进度条的边框对齐 */ left: 50%; width: 0; height: 0; /* 绘制三角形箭头,颜色和进度条保持一致 */ border-top: 12px solid transparent; border-bottom: 12px solid transparent; border-left: 12px solid #012C52; /* 设置旋转原点为箭头的左侧中心,这样旋转时能沿着环形轨迹移动 */ transform-origin: left center; z-index: 1; }
步骤3:适配不同进度的动画同步
因为不同百分比的进度条动画总时长不同,我们需要给每个进度的箭头匹配对应的旋转角度和动画时长:
- 90%进度(对应360°×90%=324°):动画总时长为右侧1.8s + 左侧1.5s = 3.3s
- 70%进度(对应252°):动画总时长为1.8s + 1.2s = 3s
- 50%进度(对应180°):动画总时长为仅右侧的1.8s
- 10%进度(对应36°):动画总时长为1.8s + 0.4s = 2.2s
对应的CSS动画代码如下:
/* 不同进度对应的箭头动画 */ .progress.blue .progress-arrow { animation: arrow-rotate-90 3.3s linear forwards; } .progress.green .progress-arrow { border-left-color: #1abc9c; animation: arrow-rotate-70 3s linear forwards; } .progress.yellow .progress-arrow { border-left-color: #fdba04; animation: arrow-rotate-50 1.8s linear forwards; } .progress.pink .progress-arrow { border-left-color: #ed687c; animation: arrow-rotate-10 2.2s linear forwards; } @keyframes arrow-rotate-90 { 0% { transform: rotate(0deg); } 100% { transform: rotate(324deg); } } @keyframes arrow-rotate-70 { 0% { transform: rotate(0deg); } 100% { transform: rotate(252deg); } } @keyframes arrow-rotate-50 { 0% { transform: rotate(0deg); } 100% { transform: rotate(180deg); } } @keyframes arrow-rotate-10 { 0% { transform: rotate(0deg); } 100% { transform: rotate(36deg); } }
完整修改后的代码
下面是整合了箭头效果的完整代码,包含所有进度类型的适配:
* { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } :after, :before { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } html, body { height: 100%; } body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.428571429; color: #333333; background-color: #ffffff; } .progress{ width: 100px; height: 100px; line-height: 100px; background: none; margin: 0; box-shadow: none; position: relative; } .progress:after{ content: ""; width: 100%; height: 100%; border-radius: 50%; border: 12px solid #fff; position: absolute; top: 0; left: 0; } .progress > span{ width: 50%; height: 100%; overflow: hidden; position: absolute; top: 0; z-index: 1; } .progress .progress-left{ left: 0; } .progress .progress-bar{ width: 100%; height: 100%; background: none; border-width: 12px; border-style: solid; position: absolute; top: 0; } .progress .progress-left .progress-bar{ left: 100%; border-top-right-radius: 80px; border-bottom-right-radius: 80px; border-left: 0; -webkit-transform-origin: center left; transform-origin: center left; } .progress .progress-right{ right: 0; } .progress .progress-right .progress-bar{ left: -100%; border-top-left-radius: 80px; border-bottom-left-radius: 80px; border-right: 0; -webkit-transform-origin: center right; transform-origin: center right; animation: loading-1 1.8s linear forwards; } .progress .progress-value{ width: 90%; height: 90%; border-radius: 50%; background: white; font-size: 20px; color: #012C52; line-height: 100px; text-align: center; position: absolute; top: 5%; left: 5%; z-index: 2; } .progress.blue .progress-bar{ border-color: #012C52; } .progress.blue .progress-left .progress-bar{ animation: loading-2 1.5s linear forwards 1.8s; } .progress.yellow .progress-bar{ border-color: #fdba04; } .progress.yellow .progress-left .progress-bar{ animation: loading-3 1s linear forwards 1.8s; } .progress.pink .progress-bar{ border-color: #ed687c; } .progress.pink .progress-left .progress-bar{ animation: loading-4 0.4s linear forwards 1.8s; } .progress.green .progress-bar{ border-color: #1abc9c; } .progress.green .progress-left .progress-bar{ animation: loading-5 1.2s linear forwards 1.8s; } /* 新增箭头样式 */ .progress-arrow { position: absolute; top: -6px; left: 50%; width: 0; height: 0; border-top: 12px solid transparent; border-bottom: 12px solid transparent; border-left: 12px solid #012C52; transform-origin: left center; z-index: 1; } /* 不同进度对应的箭头动画 */ .progress.blue .progress-arrow { animation: arrow-rotate-90 3.3s linear forwards; } .progress.green .progress-arrow { border-left-color: #1abc9c; animation: arrow-rotate-70 3s linear forwards; } .progress.yellow .progress-arrow { border-left-color: #fdba04; animation: arrow-rotate-50 1.8s linear forwards; } .progress.pink .progress-arrow { border-left-color: #ed687c; animation: arrow-rotate-10 2.2s linear forwards; } @keyframes loading-1{ 0%{ -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100%{ -webkit-transform: rotate(180deg); transform: rotate(180deg); } } @keyframes loading-2{ 0%{ -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100%{ -webkit-transform: rotate(144deg); transform: rotate(144deg); } } @keyframes loading-3{ 0%{ -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100%{ -webkit-transform: rotate(90deg); transform: rotate(90deg); } } @keyframes loading-4{ 0%{ -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100%{ -webkit-transform: rotate(36deg); transform: rotate(36deg); } } @keyframes loading-5{ 0%{ -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100%{ -webkit-transform: rotate(126deg); transform: rotate(126deg); } } @keyframes arrow-rotate-90 { 0% { transform: rotate(0deg); } 100% { transform: rotate(324deg); } } @keyframes arrow-rotate-70 { 0% { transform: rotate(0deg); } 100% { transform: rotate(252deg); } } @keyframes arrow-rotate-50 { 0% { transform: rotate(0deg); } 100% { transform: rotate(180deg); } } @keyframes arrow-rotate-10 { 0% { transform: rotate(0deg); } 100% { transform: rotate(36deg); } } @media only screen and (max-width: 990px){ .progress{ margin-bottom: 20px; } }
<div class="container"> <div class="row"> <div class="col-md-3 col-sm-6"> <div class="progress blue" style="margin-top:50px;"> <span class="progress-left"> <span class="progress-bar"></span> </span> <span class="progress-right"> <span class="progress-bar"></span> </span> <div class="progress-value">90%</div> <div class="progress-arrow"></div> </div> </div> <div class="col-md-3 col-sm-6"> <div class="progress green" style="margin-top:50px;"> <span class="progress-left"> <span class="progress-bar"></span> </span> <span class="progress-right"> <span class="progress-bar"></span> </span> <div class="progress-value">70%</div> <div class="progress-arrow"></div> </div> </div> <div class="col-md-3 col-sm-6"> <div class="progress yellow" style="margin-top:50px;"> <span class="progress-left"> <span class="progress-bar"></span> </span> <span class="progress-right"> <span class="progress-bar"></span> </span> <div class="progress-value">50%</div> <div class="progress-arrow"></div> </div> </div> <div class="col-md-3 col-sm-6"> <div class="progress pink" style="margin-top:50px;"> <span class="progress-left"> <span class="progress-bar"></span> </span> <span class="progress-right"> <span class="progress-bar"></span> </span> <div class="progress-value">10%</div> <div class="progress-arrow"></div> </div> </div> </div> </div>
关键说明
- 箭头的
transform-origin设置为left center,这样旋转时会以箭头的左侧为圆心,刚好贴合环形进度条的轨迹。 - 动画时长必须和对应进度条的总动画时长一致(右边进度条动画时长 + 左边进度条动画时长),这样箭头才能和进度条同步运动。
- 箭头的颜色要和对应进度条的边框颜色保持一致,保证视觉统一。
内容的提问来源于stack exchange,提问作者Harish K
相关产品推荐
相关产品推荐

