环形进度条的实现方法总结和动态时钟绘制(CSS3、SVG、Canvas)
kart
8年前
<h2>缘由:</h2> <p>在某一个游戏公司的笔试中,最后一道大题是,“用CSS3实现根据动态显示时间和环形进度【效果如下图所示】,且每个圆环的颜色不一样,不需要考虑 IE6~8的兼容性”。当时第一想法是用SVG,因为SVG在画弧线方面是行家呀,另外Canvas也是极好的选择。但是规定了不能用SVG和 Canvas,我想还可以使用CSS3的clip和rotate属性,但当时脑抽的我竟记不起clip的语法袅(囧~)。笔试结束后,便去查clip属性 的使用,总结了实现环形进度条的方法,于是便有了下文。</p> <p><img alt="环形进度条的实现方法总结和动态时钟绘制(CSS3、SVG、Canvas)" src="https://simg.open-open.com/show/813ee127a72124f04d7fed55651960b3.png"></p> <p>图1:动态时钟样式</p> <h2>一. CSS3实现 + JS判断</h2> <p>看到圆环,而且不允许使用Canvas和SVG的话,大概都会想到用图片或者border-radius。但是可惜border属性并不能实现百分比边框。比较常见的做法是把标示进度的圆环切分成两半,并通过旋转半圆环和遮罩效果实现百分比进度效果。</p> <p>我实现的思路:</p> <p>1 . 把标示进度的圆环分成视觉上的左右两半(用CSS3的clip属性或者border-color:transparent);并用非标示进度色的半圆环遮罩住标示进度色的左半圆环。</p> <p>2 . 在0~50%阶段,先把标示进度的右半圆环隐藏掉(display:none或opacity:0);左半圆环先被用非标示进度色的半圆环遮罩,当左半圆环顺时针旋转时即可视觉上显示进度色的逐数改变;</p> <p>3 . 在50%~100%阶段,左半圆环停止旋转,右半圆环开始旋转,这样就能实现连贯的圆环旋转效果。另外,原本在左半圆环上方的遮罩层应隐藏,否则会遮盖住右半圆环的旋转效果;</p> <p>首先实现圆环效果,代码如下:<br> HTML代码:</p> <pre> <code><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> <p>CSS代码:</p> <pre> <code>/* 进度条样式 */ .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; } </code></pre> <p>JavaScript代码:</p> <pre> <code>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> <p><a href="/misc/goto?guid=4959677076063517270">在线演示请点击这里~</a></p> <h2>二. SVG实现</h2> <p>SVG中路径的动态描边一般使用stroke-dasharray和stroke-dashoffset这两个属性来创建虚线,通过虚线的实线与间隔来达到视觉上的动态描边效果。</p> <p>实现思路:</p> <p>通过使用使stroke-dasharray的长度恰好等于圆环的周长,再通过动态设置stroke-dashoffset的大小来填充透明圆环,使视觉上成进度条样式。</p> <p>代码如下:<br> HTML代码:</p> <pre> <code><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"> </code></pre> <p>CSS代码:</p> <pre> <code>#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); } </code></pre> <p>JavaScript代码:</p> <pre> <code>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> <p><a href="/misc/goto?guid=4959677076143555787">在线演示请戳这里~</a></p> <h2>三. HTML5的Canvas实现</h2> <p>HTML5的Canvas最擅长的技能之一就是画图表。在Canvas中,可以通过arc(x1, y1, r, beginAngle, endAngle, boolean)函数来通过定义起始角度和终点角度来画出一段弧形。</p> <p>HTML代码:</p> <pre> <code><canvas id="circle" width="130" height="130"></canvas> <input id="range" type="range" min="0" max="360" step="1" value="0"> </code></pre> <p>JavaScript代码:</p> <pre> <code>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> <p> </p> <p><a href="/misc/goto?guid=4959677076218118957">在线演示请戳这里~</a></p> <p> </p> <h2>四. sprite图实现</h2> <p>sprite图实现的原理就是画好每一个关键帧的状态图片,然后通过动态改变每一帧中background的position值。这种方法比较原始,兼容性很好,而且可以花样设计,但是由于引入多个状态图,可能会导致下载量很大,而且比较臃肿。</p> <p>在这里就不详细讲解啦,这么简单的你们都懂~(真相是我真不想画那么多个状态图~( ╯□╰ )~)</p> <h2>动态时钟绘制(CSS3、SVG、Canvas)</h2> <p>来为这次缘由画上顿号。</p> <p>这篇教程源于笔试题中的最后一题,感觉智商被碾压了,所以归来开始思考其实现方案。题目如下:</p> <p>“用CSS3实现根据动态显示时间和环形进度,且每个圆环的颜色不一样。不需要考虑IE6~8的兼容性。”效果图如上图1所示。</p> <p>如下是我分别用CSS3、SVG、Canvas实现的动态时钟和环形进度实例。</p> <h3>1. CSS3实现的动态时钟和环形进度</h3> <p><a href="/misc/goto?guid=4959677076301603150">在线演示请戳这里~</a></p> <h3>2. SVG实现的动态时钟和环形进度</h3> <p><a href="/misc/goto?guid=4959677076376946993">在线演示请戳这里~</a></p> <h3>3. HTML5的canvas实现的动态时钟和环形进度</h3> <p><a href="/misc/goto?guid=4959677076463756518">在线演示请戳这里~</a></p> <h2>源码下载</h2> <p>1 . <a href="/misc/goto?guid=4959677076536133585">环形进度条的实现(CSS3、SVG、canvas)+JS 源码包下载~</a></p> <p>2 . <a href="/misc/goto?guid=4959677076625618360">环形动态时钟绘制(CSS3、SVG、canvas)+JS 源码包下载~</a></p> <p>来自:http://www.dengzhr.com/frontend/css/421</p>