参考来源

Radial progress indicator using CSS》,该文核心是用纯CSS来做一个环形的进度条。纯css的意思就是连百分比这种数字,都是css生成的。文章作者采取的方式是生成100个span标签,然后为这100个标签生成100段css代码(用less生成,代码量倒不大,只是生成的代码量会很大),不知道有没有更NB更省资源的css方案。
而我的需求很简单,只需要学习怎么画环进进度条即可,进度掌控当然得由js来通知(比如下载进度,或者音乐播放进度)
对E文没有恐惧感的话,建议直接看原作者的文,我这不是全文翻译,而是自己的练习。

注:为了方便,我只对chrome写了样式,所以如果要运行我在jsfiddle里面写的例子,最好选webkit系的浏览器

起步

原作者讲解得很详细,我们直接跳过吧,自己学习css3关于动画的部分,总之,先成功一个例子再说:

html

<div class="radial-progress">
<div class="circle">
<div class="mask">
<div class="fill"></div>
</div>
</div>
</div>

一个容器,一个一环形元素,再加一个mask,和fill,后面介绍

css

为了直接在jsfiddle上使用,我也用less吧,毕竟只要一句js声明即可客户端解析(插一句,工程项目建议用sass,因为有compass这个库,大大减轻工作量)

@size:120px;
@bgcolor:#ddd;
@bgcolor1:#cc7;
@duration:1s;
*{margin:0;padding:0;}
.radial-progress{
margin:30px 50px;
position: relative;
.comm(){
width:@size;
height:@size;
position: absolute;
top:0;
left:0;
border-radius: 50%;
}
.circle{
.comm;
background: @bgcolor;
.mask{
clip:rect(0,@size,@size,@size/2);
.comm;
}
.fill{
background: @bgcolor1;
clip:rect(0,@size/2,@size,0);
transition:-webkit-transform @duration;.comm;}
}
}

js

$('head style[type="text/css"]').attr('type', 'text/less');
less.refreshStyles();
$(function(){
var m=$(".fill"),el=$("#deg").val(60),cur=$("#cur");
$("#start").click(function(){
var deg=el.val()||60;
m.css("transform","rotate("+deg+"deg)");
cur.text(deg);
el.val(Math.ceil(Math.random()*180));
});
$("#start").click();
});

讲解

  • 要想弧形运动,首先想到了css3的rotate,并且rotate的旋转原点正好是中心,不需要额外设置,所以我们选择了这个属性。
  • 其次,进度条从无到有,显然不能像直线进度条一样,设置宽度和高度即可,我们只能选择一个层从另一个层的遮挡中逐渐出现这种方案,这就是我们取名叫mask和fill的原因.
  • 上面就是我们的实现:把进度条所属的块只显示左半边,而盛放进度条用的容器,却只显示右半边,(只显示半边是怎么做到的?学习CSS3 clip),这样,我们看不到任何进度条所属的色块,因为它压根就没出现在容器范围内。
  • 然后我们让左边的进度条色块进行旋转,一旦旋转到右侧,色块自然就能在右侧看到了(容器一直在右侧,但是无底色,只有进度条有底色,所以核心就是让进度条色块通过旋转,进入到容器所在的位置内
  • 此图表示左边色块大概转了一百多度转到了右边
  • 最后,加上50%的弧度,圆形就出现了
  • 看看效果:http://jsfiddle.net/walker/smMzz/,饼图是制作成功了

360度

上面的例子做完后,你应该发现这种转法,最多只能转180度啊!好吧,于是我们如法泡制,画一个左边的容j器和右边的色块:

html

<div class="radial-progress">
<div class="circle">
<div class="mask left">
<div class="fill"></div>
</div>
<div class="mask right">
<div class="fill"></div>
</div>
</div>
</div>

css

@size:120px;
@bgcolor:#ddd;
@bgcolor1:#cc7;
@duration:1s;
*{margin:0;padding:0;}
.radial-progress{margin:30px 50px; position: relative;
.comm(){
width:@size;height:@size;position: absolute;top:0;left:0;border-radius: 50%;
}
.circle{
background: @bgcolor;.comm;
.mask,.fill{.comm;}
.fill{
background: @bgcolor1;
transition:-webkit-transform @duration;
}
.left{
clip:rect(0,@size/2,@size,0);
.fill{clip:rect(0,@size,@size,@size/2);}
}
.right{
clip:rect(0,@size,@size,@size/2);
.fill{clip:rect(0,@size/2,@size,0);}
}
}
}

js不变,直接运行http://jsfiddle.net/walker/smMzz/1/

显然不是我们要的效果

改进

这时作者做了大胆的改动,别的进度条方案我还没来得及研究,总之他这种是非常“别扭”的,管它呢,先实现,后面的就都不贴代码了,每一节后面都有我贴的jsfiddle的地址,可以直接去看源码。

  • 首先,去掉了“左,右”蒙板的概念,而是把两个蒙板都并列摆在右侧(一个叫half,一个叫full),蒙板包含的色块仍然叫fill,这样js一次就同时旋转了两个色块。
  • 这样的结果肯定是没有任何变化啊!因为两个层仍然是叠在一起的。所以,作者又让.full这个层整个蒙板也旋转同样的角度!【注意】,此时两个蒙板其实已经不重合了。这样,本来两个重叠的色块,因为某一个容器继续旋转了同样的角度,比如30度,视觉上就出现了60度范围的色块!
  • 所以说别扭,是别扭在,我们封装这种进度条,其实最大只需要旋转180度。
  • 见结果:http://jsfiddle.net/walker/smMzz/2/
  • 最后,因为事实上是两个色块拼接的,拼接处有一条细线(只有在动画进行的过程中才有),仔细看上面链接的演示。于是作者继续给出解决方案:在half层里面添加一个色块,class也是fill,所以也会被js控制进行旋转,但是这个fix的fill是直接按2倍角度旋转的,这样在旋转的过程中,因为速度的不同,它就挡住了那条白线(这里才需要对js进行一点修改,2倍旋转fix层)。
  • 如果对用户体验没这么关心(怎么可能!),其实这件事可以不做的。修改后见:http://jsfiddle.net/walker/smMzz/3/

把饼图改成环图

至此已经大功告成,我们中间再添加一个跟底色一样的div把它变圆不就可以了吗?
对的,顺便还加了点内阴影外阴影,这样就有3D甜甜圈的效果了:http://jsfiddle.net/walker/smMzz/4/

如果要看代码,就注意一下,这一步只是添加了一个.inset和一个.shadow,对应的css看源码。

我们这里就不要3D了,简化一下,把3D啊,阴影啊,都去掉:http://jsfiddle.net/walker/smMzz/5/

模拟进度条

至此,我参考的老外原文已经和我下面的东西不沾边了,感兴趣他怎么用纯css来实现动态进度条的可继续在原文观看,我这里基本上是js部分了,目的是让进度条响应当前进度

  • 我们添加一个div来放数字,位置就在.inset里面,以百分号表示
  • 我们封装一个js方法,见源码的runprocess方法,其中process其实就是把前面onclick的内容给提取了出来,只需要传入一个100以内的数字
  • 而run方法则包含了一定业务逻辑此处的逻辑是传入一个开始进度和结束进度,我就每1%调用一次进度条(真实的业务逻辑一般为:我监测下载进度,或歌曲播放进度,一旦有变化,就通知这个函数更改UI)
  • 讲解得比较抽象,运行一下结果再看代码:http://jsfiddle.net/walker/smMzz/6/
  • 补充一句,前面之所以要有1秒的动画切换时间,纯粹为了好看(各种js生成的图表,也是为了展示这个生成过程,好看),而我们用来做“被通知”的进度条的时候,就没必要了,比如你现在在89%,要跳到90%,那就直接转到90%即可,而不是需要这1S的转场时间。因为事实上我们已经有这个时间了:下载的时间,歌曲播放的时间。所以我把transition去掉了。

模拟播放器

上面的例子是模拟下载或者上传进度条。什么意思?不管是上传,还是下载,进度只是一个“状态”,你不能手动更改这个状态,而播放器则不同,你更改这进度条的百分比,应该能影响歌曲或影片从哪个时间点开始播放,因此,我们需要响应点击事件,同时还要会计算点击位置的角度:

      • 我们选择.circle作为点击事件的响应对象,因为不受.mask.fill元素是否可见的影响。并把其鼠标状态改为手形
      • 一旦进度条出现,就会覆盖在.circle上面,所以我们又要把.mask.fill这两个层设为鼠标穿透(用pointer-events:none实现),以免点击不到.circle元素
      • 计算角度的函数见源码,我也是网上搜的,有效。
      • 角度转化成百分比,调用run函数,it works
      • 最后,干脆替换一个播放器按钮
      • 见示例: http://jsfiddle.net/walker/smMzz/7/

CSS制作环形进度条的更多相关文章

  1. iOS 开发技巧-制作环形进度条

    有几篇博客写到了怎么实现环形进度条,大多是使用Core Graph来实现,实现比较麻烦且效率略低,只是一个小小的进度条而已,我们当然是用最简单而且效率高的方式来实现. 先看一下这篇博客,博客地址:ht ...

  2. 【CSS】环形进度条

    效果图 原理剖析 1.先完成这样一个半圆(这个很简单吧) 2.overflow: hidden; 3.在中间定位一个白色的圆形做遮挡 4.完成另一半 5.使用animate配合时间完成衔接 源码 &l ...

  3. 微信小程序纯css制作圆形进度条所遇到的问题

    wrapBox:最外层盒子,背景色为进度条的颜色 leftBox/rightBox:半宽等长 左/右浮动的盒子,背景色为灰色 roundMask:居中的盒子 用来遮盖leftBox和rightBox ...

  4. 利用jQuery和CSS实现环形进度条

    实现原理 原理非常的简单,在这个方案中,最主要使用了CSS3的transform中的rotate和CSS3的clip两个属性.用他们来实现半圆和旋转效果. 半环的实现 先来看其结构. HTML < ...

  5. 图解CSS3制作圆环形进度条的实例教程

    圆环形进度条制作的基本思想还是画出基本的弧线图形,然后CSS3中我们可以控制其旋转来串联基本图形,制造出部分消失的效果,下面就来带大家学习图解CSS3制作圆环形进度条的实例教程 首先,当有人说你能不能 ...

  6. [Swift通天遁地]一、超级工具-(2)制作美观大方的环形进度条

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  7. 【css】如何实现环形进度条

    最近团队的童鞋接到了一个有关环形进度条的需求,想要还原一个native的沿环轨迹渐变进度条的效果,看到这个效果的时候,笔者陷入了沉思.. 环形进度条的效果,最先想到的就是使用CSS利用两个半圆的hac ...

  8. N 种仅仅使用 HTML/CSS 实现各类进度条的方式

    本文将介绍如何使用 HTML/CSS 创建各种基础进度条及花式进度条及其动画的方式,通过本文,你可能可以学会: 通过 HTML 标签 <meter> 创建进度条 通过 HTML 标签 &l ...

  9. iOS一分钟学会环形进度条

    有几篇博客写到了怎么实现环形进度条,大多是使用Core Graph来实现,实现比较麻烦且效率略低,只是一个小小的进度条而已,我们当然是用最简单而且效率高的方式来实现.先看一下这篇博客,博客地址:htt ...

随机推荐

  1. RK3288 GPIO

    简介GPIO, 全称 General-Purpose Input/Output(通用输入输出),是一种软件运行期间能够动态配置和控制的通用引脚.RK3288有9组 GPIO bank: GPIO0,G ...

  2. 在本地运行正常的静态网页放到tomcat中却显示异常的原因

    在本地写好了一个个人网站,本地直接用浏览器运行,很顺利,然而把网站放到Tomcat里面,却发现图片显示不出来,这就奇怪了. 后来发现,我的网站的Image文件夹用了大写“I”,而网页里面的路径用了小写 ...

  3. vue-calendar 基于 vue 2.0 开发的轻量,高性能日历组件

    vue-calendar-component 基于 vue 2.0 开发的轻量,高性能日历组件 占用内存小,性能好,样式好看,可扩展性强 原生 js 开发,没引入第三方库 Why Github 上很多 ...

  4. 关于if判断和switch

    1.if判断: if(条件1){ 执行语句: } else if(条件2)}{ 执行语句2: } else{ 执行语句3: } if里面可以有无限个else if,而else if里面能嵌套无限个if ...

  5. MSRHook与SSDTHook

    //方式1:MSR Hook #include <ntifs.h> UINT32 oldaddr = ; UINT32 pidtoprotect = ; PCLIENT_ID pid = ...

  6. MySQL数据库SQL语句基本操作

    一.用户管理: 创建用户: create user '用户名'@'IP地址' identified by '密码'; 删除用户: drop user '用户名'@'IP地址'; 修改用户: renam ...

  7. websocket session共享

    单机运行 用户a通过服务器进入房间room,用户b也通过房间进入room,用户之间是通过session来通话的,所以session直接存储在集合中就可以了. 因为session存储在一台服务器的集合中 ...

  8. spring整合redis(哨兵模式)

    首先服务器搭建哨兵模式(我这里使用的是Windows8系统),感谢两位博主,少走不少弯路,在此给出链接:服务器哨兵模式搭建和整合哨兵模式 什么一些介绍就不介绍了,可以看一下连接,比较详细,初次接触,当 ...

  9. 如何启动linux的telnet服务--转载

    如何启动linux的telnet服务 如何启动linux的telnet服务 步骤如下: 1.如果安装了telnet.telnet-server的rpm包,就跳到2.,否则安装这个包. 2.修改teln ...

  10. 第八次作业:聚类--K均值算法:自主实现与sklearn.cluster.KMeans调用

    import numpy as np x = np.random.randint(1,100,[20,1]) y = np.zeros(20) k = 3 def initcenter(x,k): r ...