继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

css动画骚操作:写饼图

摇曳的蔷薇
关注TA
已关注
手记 324
粉丝 54
获赞 169

前言

基本思路

1. 创建一个A/B两色各占一半的圆形
2. 用一个底色为A,相同半径的半圆遮盖颜色为B的那一半
3. 让半圆随着圆的圆心旋转

https://img3.mukewang.com/5d31c42f0001d80402980288.jpg

demo

第一步:创建两色的圆形

css线性渐变liner-gradient可以创建多种颜色的元素,是一个非常好用的属性。

liner-gradient语法

<linear-gradient> = linear-gradient([ [ <angle> | to <side-or-corner> ] ,]? <color-stop>[, <color-stop>]+)<side-or-corner> = [left | right] || [top | bottom]<color-stop> = <color> [ <length> | <percentage> ]?
下述值用来表示渐变的方向,可以使用角度或者关键字来设置:<angle>:用角度值指定渐变的方向(或角度)。
to left:设置渐变为从右到左。相当于: 270deg
to right:设置渐变从左到右。相当于: 90deg
to top:设置渐变从下到上。相当于: 0deg
to bottom:设置渐变从上到下。相当于: 180deg。这是默认值,等同于留空不写。<color-stop> 用于指定渐变的起止颜色:<color>:指定颜色。<length>:用长度值指定起止色位置。不允许负值<percentage>:用百分比指定起止色位置。

代码

.round{    width:200px;height:200px;    border-radius: 50%;    background: yellowgreen;    background-image: linear-gradient(to right,transparent 50%,#655 0);
}

https://img2.mukewang.com/5d31c4320001738302410174.jpg

demo

第二步:使用伪类创建半圆进行遮挡

这里使用border-radius的扩展语法。

设置或检索对象使用圆角边框。提供2个参数,2个参数以“/”分隔,每个参数允许设置1~4个参数值,第1个参数表示水平半径,第2个参数表示垂直半径,如第2个参数省略,则默认等于第1个参数。

水平半径:如果提供全部四个参数值,将按上左(top-left)、上右(top-right)、下右(bottom-right)、下左(bottom-left)的顺序作用于四个角。
如果只提供一个,将用于全部的于四个角。
如果提供两个,第一个用于上左(top-left)、下右(bottom-right),第二个用于上右(top-right)、下左(bottom-left)。
如果提供三个,第一个用于上左(top-left),第二个用于上右(top-right)、下左(bottom-left),第三个用于下右(bottom-right)。
垂直半径也遵循以上4点。

这里稍微解释下垂直半径水平半径
因为我们平常使用的是border-radius基本都是一组参数,即不含有'/'的写法,所以圆角基本都是正圆形。看下图55pt的那个半径是水平半径,25pt的是垂直半径。

https://img4.mukewang.com/5d31c436000147ca03400216.jpg

图片转自http://www.coin163.com/it/5256227506064738600/css3-html

.round::before{    content:'';    display: block;    margin-left: 50%;    height:100%;    background-color: inherit;    border-radius: 0 100% 100% 0 /50%;
}

这里为了说明,先把半圆的背景从inherit改为yellow。

https://img3.mukewang.com/5d31c43900011feb02340230.jpg

demo

这段border-radius: 0 100% 100% 0 /50%;展开来看:右上和右下角的垂直半径为50%,水平半径为100%.

    border-top-left-radius: 0px 50%;    border-top-right-radius: 100% 50%;    border-bottom-right-radius: 100% 50%;    border-bottom-left-radius: 0px 50%;

第三步: 让半圆旋转

先设置旋转点,需要用到transform-origin这个属性。我们希望他是围绕圆心,也就是半圆左边缘的中点来旋转的,可以写成transform: 0 50%,简写是transform:left

transform-origin

设置或检索对象以某个原点进行转换。
该属性提供2个参数值。
如果提供两个,第一个用于横坐标,第二个用于纵坐标。
如果只提供一个,该值将用于横坐标;纵坐标将默认为50%。
transform-origin:[ <percentage> | <length> | left | center① | right ] [ <percentage> | <length> | top | center② | bottom ]?<percentage>:用百分比指定坐标值。可以为负值。<length>:用长度值指定坐标值。可以为负值。
left:指定原点的横坐标为left
center①:指定原点的横坐标为center
right:指定原点的横坐标为right
top:指定原点的纵坐标为top
center②:指定原点的纵坐标为center
bottom:指定原点的纵坐标为bottom

接着是使用transform属性rotate()来让半圆旋转。

.round::before{    content:'';    display: block;    margin-left: 50%;    height:100%;    background-color: inherit;    border-radius: 0 100% 100% 0 /50%;    transform-origin: left;    transform: rotate(.1turn)
}

https://img1.mukewang.com/5d31c43d0001a50402310214.jpg

demo

不过,想要处理角度大于180度时,需要更改伪类元素的背景颜色。

写个进度动画


demo

.round::before{    content:'';    display: block;    margin-left: 50%;    height:100%;    background-color: inherit;    border-radius: 0 100% 100% 0 /50%;    transform-origin: left;    transform: rotate(.01turn);    animation: spin 1s linear infinite,
                changeBG 2s step-end infinite;
}

@keyframes spin{    to {transform: rotate(.5turn)}
}

@keyframes changeBG{
    50% {background-color: #655;}
}

animation-time-function

steps(<integer>[, [ start | end ] ]?):接受两个参数的步进函数。第一个参数必须为正整数,指定函数的步数。第二个参数取值可以是start或end,指定每一步的值发生变化的时间点。第二个参数是可选的,默认值为end。
step-start:等同于 steps(1, start)
step-end:等同于 steps(1, end)

注意spin的时间间隔要为changeBG的一半,此时更改伪元素半圆的背景颜色。

不同比例的饼图

比如我们需要根据写在html中的数字来显示不同比例的饼图。

<div class="round">0.3</div><div class="round">0.8</div>

解决方案是设置animation-delay为负数,并设置动画为暂停状态。它意味着动画会立即开始播放,但会自动前进到延时值的绝对值处,就好像动画在过去已经播放了指定的时间一样。因此实际效果就是动画跳过指定时间而从中间开始播放了。

.round::before{    /* 省略了上段相同的代码 */
    animation: spin 0.5s linear infinite,
                changeBG 1s step-end infinite;    animation-play-state: paused; /* 设置动画为暂停状态 */}

现在,我们要从html中读取比值,然后将animation-delay写到伪类上。

/* 因为querySelector不支持查找伪类,在使用vanilla js的情况下只能创建<style>,插入到<head>中了。。 */const style = document.createElement('style');document.head.appendChild(style);const {sheet} = style;/* 使用es6 ... rest/spread操作符 可以将类数组转变为数组 */const eles=[...document.getElementsByClassName('round')] 
 eles.forEach((ele,idx)=>{    const text=ele.textContent    /* 注意要加在伪类上 */
    sheet.addRule(`.round:nth-child(${idx+1})::before`,`animation-delay:-${text}s`)
    })

最终的效果

https://img3.mukewang.com/5d31c4470001a9e002420474.jpg

demo



作者:mytac
链接:https://www.jianshu.com/p/269d7bae268b


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP