zoukankan      html  css  js  c++  java
  • 环形进度条的实现方法总结和动态时钟绘制(CSS3、SVG、Canvas)

    缘由:

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

    clock

    图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代码:

     
    1. <div class="circle">
    2. <div class="track"></div>
    3. <div class="left transition-rotate"></div>
    4. <div class="right transition-rotate"></div>
    5. <div class="mask"></div>
    6. <span id="hour">0</span><span class="percent">%</span>
    7. </div>
    8. <input id="range" type="range" min="0" max="100" step="1" value="0">

    CSS代码:

     
    1. /* 进度条样式 */
    2. .circle {
    3. position: relative;
    4. width: 130px;
    5. height: 130px;
    6. text-align: center;
    7. }
    8. .circle .track, .circle .mask, .circle .left, .circle .right {
    9. width: 130px;
    10. height: 130px;
    11. position: absolute;
    12. top: 0;
    13. left: 0;
    14. border-radius: 50%;
    15. border: 20px #e7e7e7 solid;
    16. -webkit-box-sizing: border-box;
    17. -moz-box-sizing: border-box;
    18. box-sizing: border-box;
    19. }
    20. .circle .mask, .circle .left, .circle .right {
    21. clip: rect(0 65px 130px 0);
    22. }
    23. .circle .left, .circle .right {
    24. border-color: #6FEC6F;
    25. }
    26. .circle .right {
    27. opacity: 0;
    28. -webkit-transform: rotate(180deg);
    29. -moz-transform: rotate(180deg);
    30. -ms-transform: rotate(180deg);
    31. -o-transform: rotate(180deg);
    32. transform: rotate(180deg);
    33. }
    34. /* 进度显示文字样式 */
    35. .circle #hour {
    36. color: #666;
    37. font-size: 48px;
    38. line-height: 130px;
    39. }
    40. .circle .percent {
    41. font-size: 20px;
    42. color: #999;
    43. margin-left: 5px;
    44. }
    45. .transition-rotate {
    46. -webkit-transition: transform .1s ease-in-out;
    47. -moz-transition: transform .1s ease-in-out;
    48. -ms-transition: transform .1s ease-in-out;
    49. -o-transition: transform .1s ease-in-out;
    50. transition: transform .1s ease-in-out;
    51. }

    JavaScript代码:

     
    1. var circle = document.querySelectorAll(".circle")[0];
    2. var mask = document.querySelectorAll(".mask")[0];
    3. var left = document.querySelectorAll(".left")[0];
    4. var right = document.querySelectorAll(".right")[0];
    5. var range = document.getElementById("range");
    6. var hour = document.querySelectorAll("#hour")[0];
    7. var n;
    8. changeHour();
    9. range.oninput = changeHour;
    10. function changeHour() {
    11. hour.innerHTML = range.value;
    12. n = range.value;
    13. if(n <= 50) {
    14. left.style.webkitTransform="rotate(" + 3.6 * n + "deg)";
    15. right.style.opacity = 0;
    16. mask.style.opacity = 1;
    17. }else {
    18. right.style.opacity = 1;
    19. mask.style.opacity = 0;
    20. left.style.webkitTransform="rotate(" + 180 + "deg)";
    21. right.style.webkitTransform="rotate(" + 3.6 * n + "deg)";
    22. }
    23. }

    效果如下:

    在线演示请点击这里~

     

    二. SVG实现

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

    实现思路:

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

    代码如下: 
    HTML代码:

     
    1. <svg id="circleProcess" xmlns="http://www.w3.org/2000/svg">
    2. <circle id="circle" cx="50%" cy="50%" r="40%" stroke-width="10%"></circle>
    3. </svg>
    4. <input id="range" type="range" min="0" max="255" step="1" value="0">

    CSS代码:

     
    1. #circleProcess {
    2. position: relative;
    3. top: 0;
    4. left: 0;
    5. width: 200px;
    6. height: 200px;
    7. stroke-dasharray: 255%;
    8. stroke-dashoffset: 255%;
    9. stroke: #6FEC6F;
    10. fill: none;
    11. -webkit-transform: rotate(-90deg);
    12. -moz-transform: rotate(-90deg);
    13. -ms-transform: rotate(-90deg);
    14. -o-transform: rotate(-90deg);
    15. transform: rotate(-90deg);
    16. }

    JavaScript代码:

     
    1. var circleProcess = document.getElementById("circleProcess");
    2. var circle = document.getElementById("circle");
    3. var range = document.getElementById("range");
    4. // 滑动条的值
    5. var rangeValue;
    6. range.oninput = function() {
    7. rangeValue = Number(range.value);
    8. circle.setAttribute("stroke-dashoffset", (255 - rangeValue) + "%");
    9. }

    效果如下:

    在线演示请戳这里~

     

    三. HTML5的Canvas实现

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

    HTML代码:

     
    1. <canvas id="circle" width="130" height="130"></canvas>
    2. <input id="range" type="range" min="0" max="360" step="1" value="0">

    JavaScript代码:

     
    1. var range = document.getElementById("range");
    2. var rangeValue; // 滑动条获得的是度数值
    3. var circle = document.getElementById("circle");
    4. var circleWidth = circle.width;
    5. var circleHeight = circle.height;
    6. var circleContext = circle.getContext("2d");
    7. var circleValue = {
    8. x: 65,
    9. y: 65,
    10. r: 45,
    11. beginAngle: - Math.PI / 2,
    12. endAngle: 0
    13. };
    14. // 样式
    15. circleContext.lineWidth = 20;
    16. circleContext.strokeStyle = "#6FEC6F";
    17. // 描绘进度圆环
    18. function drawCircle() {
    19. circleContext.restore();
    20. // 清空当前路径
    21. circleContext.clearRect(0,0, circleWidth, circleHeight);
    22. // 把range的度数值换成Math.PI值
    23. rangeValue = Number(range.value); // 滑动条获得的是度数值
    24. circleValue.endAngle = circleValue.beginAngle + (rangeValue / 360) * 2 * Math.PI;
    25. circleContext.beginPath();
    26. // 绘制圆弧
    27. circleContext.arc(circleValue.x, circleValue.y, circleValue.r, circleValue.beginAngle, circleValue.endAngle, false);
    28. circleContext.stroke();
    29. circleContext.save();
    30. }
    31. // 滚动条滑动动画
    32. range.oninput = drawCircle;
    33. 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 源码包下载~

  • 相关阅读:
    spring快速入门
    Vue整合ElementUI搭建项目
    .Net的Rsa解密
    Maven配置国内仓库
    pom.xml
    SpringBoot文件打包后修改配文件
    .net 过滤器
    c#语法糖汇总
    git修改远程地址
    abp Application层,接口服务层,获取请求的信息
  • 原文地址:https://www.cnblogs.com/nifengs/p/5287906.html
Copyright © 2011-2022 走看看