使用canvas、SVG、css+js实现环形进度条

1、css+js
思路:
1、将环形的圆看成两个半圆;
2、0-50的时候,视觉上是右半圆开始展示进度条,但是在实现上是左半圆开始以右顺时针旋转;
3、50-100的时候,视觉上是左半圆开始展示进度条,但是实现上是右半圆开始向左旋转
4、开始时,右半圆肯定是不显示的,只有在50-100时才显示出来
5、开始时,左半圆肯定要展示的,不然旋转也看不出效果,但是这样左边的旋转就能看出来,所以要一个遮罩将左边遮挡住
代码如下:

<!DOCTYPE html>
<html>
 <head>
     <meta charset="UTF-8">
     <title></title>
     <style>
         #start{
             height: 200px;
             width: 200px;
             margin: auto auto;
             background-color: antiquewhite;
             -webkit-touch-callout:none;
             -webkit-user-select:none;
             -khtml-user-select:none;
             -moz-user-select:none;
             -ms-user-select:none;
             user-select:none;
         }
         .circle{
             height: 200px;
             width: 200px;
             position: relative;
         }
         .circle .left ,
         .circle .right,
         .circle .mask{
             position: absolute;
             left: 0;
             top: 0;
             height: 100%;
             width: 100%;
             box-sizing: border-box;
             /*将整个矩形切成半矩形*/
             clip: rect(0,100px,200px,0);
             background-color: #fff;
         }
         .circle .left ,
         .circle .right{
             border:10px solid RED;
             border-radius: 50%;
         }
         .circle .right{
             /*将应该在右侧的半圆旋转到右边,并且将其隐藏*/
             opacity: 0;
             transform: rotate(180deg);
         }
         .trans-rotate{
             -webkit-transition: transform .1s ease-in-out;
             -moz-transition: transform .1s ease-in-out;
             -ms-transition: transform .1s ease-in-out;
             -o-transition: transform .1s ease-in-out;
             transition: transform .1s ease-in-out;
         }
     </style>
 </head>
 <body>
     <button id="start"></button>
     <div class="circle">
         <!--左半圆-->
         <div id="left" class="left trans-rotate"></div>
         <!--右半圆-->
         <div id="right" class="right trans-rotate"></div>
         <!--在前面半部分时,左半圆会开始向右边旋转,需要用这个遮挡住左边效果-->
         <div id="mask" class="mask"></div>
     </div>
     <script type="text/javascript" src="js/jquery-1.7.1.js"></script>
     <script type="text/javascript">
         var left = document.getElementById("left");
         var right = document.getElementById("right");
         var mask = document.getElementById("mask");
         var circleInter;
         var rangeValue=0;
         $(function(){
             $("#start").click(function(){
                 circleInter=setInterval(function(){
                     rangeValue=rangeValue+5;//数字越大进度进展的越快
                     if(rangeValue<=50){
                         //左半圆开始向右旋转,有进度条开始的视觉效果
                         left.style.webkitTransform="rotate("+3.6*rangeValue+"deg)";
                         //遮罩展示,将左边遮挡住,不让用户看到左边旋转的效果
                         mask.style.opacity="1";
                     }else if(rangeValue<=100){
                         right.style.opacity="1";
                         //左右半圆开始向左旋转,进度条后半部分
                         right.style.webkitTransform="rotate("+3.6*rangeValue+"deg)";
                         //将遮罩去掉,不去掉圆旋转到右边也被遮挡了,会看不到效果;
                         mask.style.opacity="0";
                     }else{
                         clearInterval(circleInter);
                     }
                 },100);
             })
         });
     </script>
 </body>
</html>

效果展示:(gif出来的有点停顿,真实的还是挺流畅的,哈哈)


IMG_0751.GIF
  1. svg
    使用svg来绘制这种二维图形真的很方便;
    思路很简单:使用svg的circle,然后动态修改circle的stroke-dashoffset;进度条就看成circle的stroke;
    代码如下:
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            #start{
                height: 200px;
                width: 200px;
                margin: auto auto;
                background-color: antiquewhite;
                -webkit-touch-callout:none;
                -webkit-user-select:none;
                -khtml-user-select:none;
                -moz-user-select:none;
                -ms-user-select:none;
                user-select:none;
            }
            #circleSvg{
                width: 200px;
                height: 200px;
                stroke-dasharray: 255%;
                stroke-dashoffset: 255%;
                stroke: red;
                fill: none;
                -webkit-transform: rotate(-90deg);
                -moz-transform: rotate(-90deg);
                -ms-transform: rotate(-90deg);
                -o-transform: rotate(-90deg);
                transform: rotate(-90deg);
            }
        </style>
    </head>
    <body>
        <button id="start">svg</button>
        <svg id="circleSvg">
            <!--cx=圆心横坐标   cy=圆心纵坐标  r=半径   stroke-width=边框的宽度-->
            <circle id="circle" cx="50%" cy="50%" r="40%" stroke-width="10%"></circle>
        </svg>
        <script type="text/javascript" src="js/jquery-1.7.1.js"></script>
        <script type="text/javascript">
            var circle = document.getElementById("circle");
            var circleInter;
            var rangeValue=0; 
            $(function(){
                $("#start").click(function(){
                    circleInter=setInterval(function(){
                        rangeValue=rangeValue+5;//数字越大进度进展的越快
                        if(rangeValue<=255){
                            circle.setAttribute("stroke-dashoffset",255-rangeValue+"%");
                        }else{
                            clearInterval(circleInter);
                        }
                    },100);
                })
            });
        </script>
    </body>
</html>

展示效果和上面css+js完成的基本一样,就不再去弄gif了,偷个懒

3.canvas
canvas画图很方便啦,直接上代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            #start{
                height: 200px;
                width: 200px;
                margin: auto auto;
                background-color: antiquewhite;
                -webkit-touch-callout:none;
                -webkit-user-select:none;
                -khtml-user-select:none;
                -moz-user-select:none;
                -ms-user-select:none;
                user-select:none;
            }
            
        </style>
    </head>
    <body>
        <button id="start">svg</button>
        <canvas id="canvas" width="200" height="200"></canvas>
        <script type="text/javascript" src="js/jquery-1.7.1.js"></script>
        <script type="text/javascript">
            var canvas = document.getElementById("canvas");
            var rangeValue=0; 
            var w = canvas.width;
            var h = canvas.height;
            var con = canvas.getContext("2d");
            var val = {
                x:w/2,
                y:w/2,
                r:w/2-10,
                beginAngle:-Math.PI/2,
                endAngle:0
            };
            con.lineWidth = 10;
            con.strokeStyle = "red";
            $(function(){
                $("#start").click(function(){
                    circleInter=setInterval(function(){
                        rangeValue = rangeValue+5;
                        if(rangeValue<=360){
                            draw();
                        }else{
                            clearInterval(circleInter);
                        }
                    },100);
                })
            });
            function draw(){
                con.restore();
                con.clearRect(0,0,w,h);
                var rangValue = Number(rangeValue);
                val.endAngle = val.beginAngle+(rangValue/360)*2*Math.PI;
                con.beginPath();
                con.arc(val.x,val.y,val.r,val.beginAngle,val.endAngle,false);
                con.stroke();
                con.save();
            }
        </script>
    </body>
</html>

其实这个是很多动图的原型,比如长按录音时外围的进度条,比如时钟等等的基础都是这个,理解了这个原理很多东西做起来都很顺手了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生x阅读 15,967评论 3 119
  • 作者/胄宁 “当我意识到你我再也不会相见的那一刻,我的血凝住了。好像如果身体不动一下的话,就会这样死去。” 这是我...
    胄宁阅读 1,390评论 10 7
  • 裂变营销:最低成本的获客之道 1.社交流量:移动互联网上最重要的免费流量 移动互联网时代最贵的是什么?是流量吗?是...
    饭局局长阅读 174评论 0 0
  • 又是新的星期五,又要上餐饮课了。这是第三次餐饮课,第一次是制作柠檬水,第二次是做牙签肉,这次要做什么...
    超帅的张轩睿阅读 220评论 0 0
  • 世界上最遥远的距离莫过于我们坐在一起,你却在玩手机。 小时候,除夕夜父母们总是聚在一起打牌,而我们在一旁看春晚亦或...
    14初识阅读 213评论 0 2