環形進度條的實現方法總結和動態時鐘繪制(CSS3、SVG、Canvas)

緣由:

在某一個游戲公司的筆試中,最后一道大題是,“用CSS3實現根據動態顯示時間和環形進度【效果如下圖所示】,且每個圓環的顏色不一樣,不需要考慮 IE6~8的兼容性”。當時第一想法是用SVG,因為SVG在畫弧線方面是行家呀,另外Canvas也是極好的選擇。但是規定了不能用SVG和 Canvas,我想還可以使用CSS3的clip和rotate屬性,但當時腦抽的我竟記不起clip的語法裊(囧~)。筆試結束后,便去查clip屬性 的使用,總結了實現環形進度條的方法,于是便有了下文。

環形進度條的實現方法總結和動態時鐘繪制(CSS3、SVG、Canvas)

圖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"> </code></pre>

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)"; } } </code></pre>

在線演示請點擊這里~

二. 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) + "%"); } </code></pre>

在線演示請戳這里~

三. 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(); </code></pre>

 

在線演示請戳這里~

 

四. 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 源碼包下載~

來自:http://www.dengzhr.com/frontend/css/421

 本文由用戶 吳青強 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!