JSFiddle - React, Tailwind, and code Playground

by walker

HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/less.js/1.7.0/less.min.js"></script>
<button id="start" style="margin:30px 0 0 50px; height:24px; width:50px;">rotate</button>
<input type="number" id="deg" value="60" step="5" min="5" max="360" style="height:20px; width:40px;" /> degree, now <i id="cur"></i> degree.
<div class="radial-progress">
    <div class="circle">
        <div class="mask full">
            <div class="fill"></div>
        </div>
        <div class="mask half">
            <div class="fill"></div>
            <div class="fill fix"></div>
        </div>
        <div class="shadow"></div>
    </div>
    <div class="inset"></div>
</div>

CSS

/*
1,容器只有右半边,内容只有左半边,所以当左半边旋转到右半边时,就可以在容器里看到内容了
2,两个半圆要想连续,处理成一左一右是不行的
3,于是处理成两个重叠的半圆,第二个半圆在形成的时候顺便把容器也跟着旋转,就有了连续的两个扇形了
3.1 顺便把动画中会出现的白边处理下(复制half一节,然后让它双倍旋转),纯粹为了提升体验。体验有什么差别,你把两种情况下的动画放大看
4,如果要做得像进度条,添加一个内圆
4.1 如果环足够宽,可以考虑给内圆加投影,然后再用一个外圆加inset的投影,这是视觉3D一些技巧,与环形进度条无关,此外,如果环只是一条细条,通通不要考虑
*/
*{margin:0;padding:0;}
.radial-progress{
    @circle-size:120px;
    @bgcolor:#eee;
    @bgcolor1:#78a;
    @duration:1s;
    @inset-size:60px;
    @inset-color:#fff;
    @shadow: 6px 6px 10px rgba(0,0,0,0.2);
    margin:30px 50px;
    position: relative;
    .comm(){
		width:@circle-size;height:@circle-size;position: absolute;top:0;left:0;border-radius: 50%;
    }
	.circle{
	     background: @bgcolor;.comm;
        .mask,.fill{.comm;}
        .mask{
            clip:rect(0,@circle-size,@circle-size,@circle-size/2);
            transition:-webkit-transform @duration;
            .fill{
                clip:rect(0,@circle-size/2,@circle-size,0);
                background: @bgcolor1;
                transition:-webkit-transform @duration;
            }
        }
        .shadow {
          width: @circle-size;
          height: @circle-size;
          position: absolute;
          border-radius: 50%;
          box-shadow: @shadow inset;
        }
    }
    .inset{
        width: @inset-size;
        height: @inset-size;
        position: absolute;
        margin-left: (@circle-size - @inset-size)/2;
        margin-top: (@circle-size - @inset-size)/2;
        background-color: @inset-color;
        border-radius: 50%;
        box-shadow:@shadow;
    }
}

JavaScript

$('head style[type="text/css"]').attr('type', 'text/less');
less.refreshStyles();	
$(function(){
    var m=$(".fill,.full"),el=$("#deg").val(60),cur=$("#cur");
    $("#start").click(function(){
        var deg=el.val()||60;
        m.css("transform","rotate("+deg+"deg)");
        $(".fix").css("transform","rotate("+deg*2+"deg)");
        cur.text(deg);
        el.val(Math.ceil(Math.random()*180));
    });
    $("#start").click();
});