栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > JavaScript

你一定想不到可以用css动画写饼图

JavaScript 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

你一定想不到可以用css动画写饼图

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

第一步:创建两色的圆形

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

liner-gradient语法
 = linear-gradient([ [  | to  ] ,]? [, ]+)

 = [left | right] || [top | bottom]

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

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

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

这里使用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的是垂直半径。

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

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

这段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:[  |  | left | center① | right ] [  |  | top | center② | bottom ]?

:用百分比指定坐标值。可以为负值。
:用长度值指定坐标值。可以为负值。
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)
}

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

写个进度动画

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

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

不同比例的饼图

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

0.3
0.8

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

.round::before{
    
    animation: spin 0.5s linear infinite,
  changeBG 1s step-end infinite;
    animation-play-state: paused; 
}

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


const style = document.createElement('style');
document.head.appendChild(style);
const {sheet} = style;

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`)
    })

最终的效果

参考资料
  1. CSS参考手册
  2. 什么是border-radius的水平半径和垂直半径?

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号