您的位置:首页 > Web前端 > CSS

环形进度条的实现方法总结和动态时钟绘制(CSS3、SVG、Canvas)

2016-03-17 16:26 731 查看

缘由:

在某一个游戏公司的笔试中,最后一道大题是,“用CSS3实现根据动态显示时间和环形进度【效果如下图所示】,且每个圆环的颜色不一样,不需要考虑IE6~8的兼容性”。当时第一想法是用SVG,因为SVG在画弧线方面是行家呀,另外Canvas也是极好的选择。但是规定了不能用SVG和Canvas,我想还可以使用CSS3的clip和rotate属性,但当时脑抽的我竟记不起clip的语法袅(囧~)。笔试结束后,便去查clip属性的使用,总结了实现环形进度条的方法,于是便有了下文。



图1:动态时钟样式

一. CSS3实现 + JS判断

看到圆环,而且不允许使用Canvas和SVG的话,大概都会想到用图片或者border-radius。但是可惜border属性并不能实现百分比边框。比较常见的做法是把标示进度的圆环切分成两半,并通过旋转半圆环和遮罩效果实现百分比进度效果。

我实现的思路:

1 . 把标示进度的圆环分成视觉上的左右两半(用CSS3的clip属性或者border-color:transparent);并用非标示进度色的半圆环遮罩住标示进度色的左半圆环。

2 . 在0~50%阶段,先把标示进度的右半圆环隐藏掉(display:none或opacity:0);左半圆环先被用非标示进度色的半圆环遮罩,当左半圆环顺时针旋转时即可视觉上显示进度色的逐数改变;

3 . 在50%~100%阶段,左半圆环停止旋转,右半圆环开始旋转,这样就能实现连贯的圆环旋转效果。另外,原本在左半圆环上方的遮罩层应隐藏,否则会遮盖住右半圆环的旋转效果;

首先实现圆环效果,代码如下:
HTML代码:

<div class="circle">


<div class="track"></div>


<div class="left transition-rotate"></div>


<div class="right transition-rotate"></div>


<div class="mask"></div>


<span id="hour">0</span><span class="percent">%</span>


</div>




<input id="range" type="range" min="0" max="100" step="1" value="0">


CSS代码:

/* 进度条样式 */


.circle {


position: relative;


width: 130px;


height: 130px;


text-align: center;


}


.circle .track, .circle .mask, .circle .left, .circle .right {


width: 130px;


height: 130px;


position: absolute;


top: 0;


left: 0;


border-radius: 50%;


border: 20px #e7e7e7 solid;


-webkit-box-sizing: border-box;


-moz-box-sizing: border-box;


box-sizing: border-box;


}


.circle .mask, .circle .left, .circle .right {


clip: rect(0 65px 130px 0);


}


.circle .left, .circle .right {


border-color: #6FEC6F;


}


.circle .right {


opacity: 0;


-webkit-transform: rotate(180deg);


-moz-transform: rotate(180deg);


-ms-transform: rotate(180deg);


-o-transform: rotate(180deg);


transform: rotate(180deg);


}


/* 进度显示文字样式 */


.circle #hour {


color: #666;


font-size: 48px;


line-height: 130px;


}


.circle .percent {


font-size: 20px;


color: #999;


margin-left: 5px;


}


.transition-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;


}


JavaScript代码:

var circle = document.querySelectorAll(".circle")[0];


var mask  = document.querySelectorAll(".mask")[0];


var left = document.querySelectorAll(".left")[0];


var right = document.querySelectorAll(".right")[0];


var range = document.getElementById("range");




var hour = document.querySelectorAll("#hour")[0];




var n;


changeHour();


range.oninput = changeHour;


function changeHour() {


hour.innerHTML = range.value;


n = range.value;


if(n <= 50) {


left.style.webkitTransform="rotate(" + 3.6 * n + "deg)";


right.style.opacity = 0;


mask.style.opacity = 1;


}else {


right.style.opacity = 1;


mask.style.opacity = 0;


left.style.webkitTransform="rotate(" + 180 + "deg)";


right.style.webkitTransform="rotate(" + 3.6 * n + "deg)";


}


}


效果如下:

在线演示请点击这里~

二. SVG实现

SVG中路径的动态描边一般使用stroke-dasharray和stroke-dashoffset这两个属性来创建虚线,通过虚线的实线与间隔来达到视觉上的动态描边效果。

实现思路:

通过使用使stroke-dasharray的长度恰好等于圆环的周长,再通过动态设置stroke-dashoffset的大小来填充透明圆环,使视觉上成进度条样式。

代码如下:
HTML代码:

<svg id="circleProcess" xmlns="http://www.w3.org/2000/svg">


<circle id="circle" cx="50%" cy="50%" r="40%" stroke-width="10%"></circle>


</svg>


<input id="range" type="range" min="0" max="255" step="1" value="0">


CSS代码:

#circleProcess {


position: relative;


top: 0;


left: 0;


width: 200px;


height: 200px;


stroke-dasharray: 255%;


stroke-dashoffset: 255%;


stroke: #6FEC6F;


fill: none;


-webkit-transform: rotate(-90deg);


-moz-transform: rotate(-90deg);


-ms-transform: rotate(-90deg);


-o-transform: rotate(-90deg);


transform: rotate(-90deg);


}


JavaScript代码:

var circleProcess = document.getElementById("circleProcess");


var circle = document.getElementById("circle");


var range = document.getElementById("range");


// 滑动条的值


var rangeValue;




range.oninput = function() {


rangeValue = Number(range.value);


circle.setAttribute("stroke-dashoffset", (255 - rangeValue) + "%");


}


效果如下:

在线演示请戳这里~

三. HTML5的Canvas实现

HTML5的Canvas最擅长的技能之一就是画图表。在Canvas中,可以通过arc(x1, y1, r, beginAngle, endAngle, boolean)函数来通过定义起始角度和终点角度来画出一段弧形。

HTML代码:

<canvas id="circle" width="130" height="130"></canvas>


<input id="range" type="range" min="0" max="360" step="1" value="0">


JavaScript代码:

var range = document.getElementById("range");


var rangeValue; // 滑动条获得的是度数值




var circle = document.getElementById("circle");


var circleWidth = circle.width;


var circleHeight = circle.height;


var circleContext = circle.getContext("2d");




var circleValue = {


x: 65,


y: 65,


r: 45,


beginAngle: - Math.PI / 2,


endAngle: 0


};




// 样式


circleContext.lineWidth = 20;


circleContext.strokeStyle = "#6FEC6F";




// 描绘进度圆环


function drawCircle() {


circleContext.restore();


// 清空当前路径


circleContext.clearRect(0,0, circleWidth, circleHeight);


// 把range的度数值换成Math.PI值


rangeValue = Number(range.value); // 滑动条获得的是度数值


circleValue.endAngle = circleValue.beginAngle + (rangeValue / 360) * 2 * Math.PI;


circleContext.beginPath();


// 绘制圆弧


circleContext.arc(circleValue.x, circleValue.y, circleValue.r, circleValue.beginAngle, circleValue.endAngle, false);


circleContext.stroke();


circleContext.save();


}


// 滚动条滑动动画


range.oninput = drawCircle;


drawCircle();


效果如下:

在线演示请戳这里~

四. sprite图实现

sprite图实现的原理就是画好每一个关键帧的状态图片,然后通过动态改变每一帧中background的position值。这种方法比较原始,兼容性很好,而且可以花样设计,但是由于引入多个状态图,可能会导致下载量很大,而且比较臃肿。

在这里就不详细讲解啦,这么简单的你们都懂~(真相是我真不想画那么多个状态图~( ╯□╰ )~)

动态时钟绘制(CSS3、SVG、Canvas)

来为这次缘由画上顿号。

这篇教程源于笔试题中的最后一题,感觉智商被碾压了,所以归来开始思考其实现方案。题目如下:

“用CSS3实现根据动态显示时间和环形进度,且每个圆环的颜色不一样。不需要考虑IE6~8的兼容性。”效果图如上图1所示。

如下是我分别用CSS3、SVG、Canvas实现的动态时钟和环形进度实例。

1. CSS3实现的动态时钟和环形进度

在线演示请戳这里~

2. SVG实现的动态时钟和环形进度

在线演示请戳这里~

3. HTML5的canvas实现的动态时钟和环形进度

在线演示请戳这里~

源码下载

1 . 环形进度条的实现(CSS3、SVG、canvas)+JS 源码包下载~

2 . 环形动态时钟绘制(CSS3、SVG、canvas)+JS 源码包下载~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: