本文由团队成员 BingLee1994 撰写,已授权涂鸦大前端独家使用,包括但不限于编辑、标注原创等权益。
你是不是有这种感觉:能用几行css
画出来,不用四处找svg
或者上传图片,就觉得特别开心呢。那么渐变就可以做很多这样的事情,比如花纹,遮罩,常见图形等。
我们熟知的有线性渐变和锥形渐变,那么今天介绍另一位伙伴 conic-gradient
锥形渐变。
兼容性
主流现代浏览器均兼容。
所有好玩高效的
css
特性均不兼容IE11,不要让他成为阻碍进步的绊脚石。
名词解释
如果你初次接触渐变呢,简单了解下:渐变由方向位置,和多个颜色驻点组成。
颜色驻点
一个颜色驻点由颜色和位置组成,用空格隔开,以下图为例:
可以看到背景由绿→红→蓝,控制颜色的圈圈就是颜色驻点,那么本图中绿和蓝分别在头尾部,红色在25%的位置,那么这个红色驻点表示为:red 25%
,处于头尾部可不必写位置。
方向与中心
上图我们明显看到渐变朝右,那么我们可以指定渐变的方向为任意角度,如下面这样 特殊的,锥形渐变和放射渐变还可以指定中心点,放射渐变还可以指定半径,原型椭圆形等。
conic-gradient
好,进入正题,什么是conic-gradient(锥形渐变)?顾名思义,看下图 发现了吗?颜色绕着中心点旋转了一周,就像圆锥一样,这就是锥形渐变,颜色驻点位置如下图红线所示,刚好在半径线上:
语法
backgrouns-image: conic-gradient([ 角度 [at 位置] ], 颜色驻点1, 颜色驻点2, 颜色驻点...)
其中中括号表示非必要属性,默认角度为0
,位置在元素正中心,大部分场景,默认的就满足需求。
颜色驻点位置除了可以使用百分比,还可以使用角度表示法。
试一试
语法看着有点长,别害怕,让我们写一个css
试试效果吧:
div {
width: 200px;
height: 200px;
background-image: conic-gradient(orange, blue 50%, purple)
}
渲染如下:沿着中心转一圈,开始由橙色转到50%变为蓝色,然后由蓝色转到360°变成紫色,就是这么简单!
那么上述50%还可以使用角度表示法:
conic-gradient(orange, blue 180deg, purple)
, 特别地,可以指定两个角度,表示颜色覆盖的角度区域,比如conic-gradient(orange, blue 180deg 240deg, purple)
.
开始画饼图
光了解而不会实际应用怎么可以呢?本文我们拿常见的饼图为实际应用案例,来更进一步体验锥形渐变。
如下图:橙色区域占30%.
差在哪里?
对比下我们上述渐变和这个饼图差在哪里呢?
没错,你发现了吗?饼图背景和橙色扇形区域(下文我们叫进度)之间的衔接处是硬的而不是渐变过渡的。
怎么做呢?不要着急,让我们先把渐变画出来:
div {
width: 200px;
height: 200px;
background-image: conic-gradient(orange, purple 30%)
}
让颜色衔接处变硬
唉~,我们惊喜发现,在起始处0°和360°,是一条橙色直接到紫色的硬线,而不是渐变,因为0° = 360 °,同一个角度位置出现两种颜色,那么两个颜色距离是0,换句话说,留给橙色渐变到紫色的空间长度为0,那自然视觉上就是没有渐变,相连处变硬,颜色直接改变。
知道了这个道理,我们就可以轻松画出上述饼图,只需要将上述30%的位置添加两个颜色驻点,这样他们两个就会直接硬性过渡。
让我们修改css代码如下:
div {
width: 200px;
height: 200px;
background-image: conic-gradient(orange 30%, purple 30%);
/* 30%的位置设置两个驻点橙色和紫色,那么在这个位置直接硬性过渡而无渐变 */
}
大功告成,最后不要忘了加个border-radius
,so easy!
饼图动起来
这么有趣的东西我们肯定要封装成组件用才能用到真实的场景,上文我们轻松画出了30%的饼图,类似地,通过更改百分比就可以让饼图动起来了,那么我们写个简单地demo控制饼图,我们通过一个滑块控制!
你可以直接拷贝如下html代码做练习
<body>
<style>
body {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#pie-chart {
width: 200px;
height: 200px;
border-radius: 100px;
background-image: conic-gradient(orange 0%, purple 0%);
margin-bottom: 24px;
}
</style>
<div id="pie-chart"></div>
<input
id="slider"
type="range"
value="0"
max="100"
min="0"
step="10"
/>
<script type="text/javascript">
// js代码写这里
</script>
</body>
添加滑块事件
本例中滑块取值为0 ~ 100
,对应颜色驻点位置,通过添加滑块的input
事件来控制饼图百分比:
<script type="text/javascript">
const elPieChart = document.getElementById('pie-chart')
const elSlider = document.getElementById('slider')
elSlider.oninput = function updateChart() {
const { value } = elSlider
//将滑块value转换为驻点位置
elPieChart.style.backgroundImage = `conic-gradient(orange ${value}%, purple ${value}%)`
}
</script>
你看,就是这么短短几句代码,饼图就能动起来了😊!
组件可定制
上面紫色饼可能不合你口味,让我们在js代码里换换颜色吧,我们定义两个变量,一个背景色,一个进度颜色,最后修改css
背景即可:
<script type="text/javascript">
// 自定义颜色
const chartColor = '#C6E9FF'
const chartProgressColor = '#4589EF'
const elPieChart = document.getElementById('pie-chart')
const elSlider = document.getElementById('slider')
// 首次渲染设置颜色
elPieChart.style.backgroundImage = `conic-gradient(${chartProgressColor} 0%, ${chartColor} 0%)`
elSlider.oninput = function updateChart() {
const { value } = elSlider
//更改饼图进度
elPieChart.style.backgroundImage = `conic-gradient(${chartProgressColor} ${value}%, ${chartColor} ${value}%)`
}
</script>
持续优化
你以为写到这里就结束了吗?让我们回过头看看代码,只是增加了个颜色需求,js
代码开始变得非常丑陋,主要出现在 elPieChart.style.backgroundImage = `conic-gradient(${chartProgressColor} ${value * 100}%, ${chartColor} ${value * 100}%)
这一坨代码非常刺眼,因为:
- 这个
css
字符串很臭长。 - 在
js
拼接css
字符串因为没有代码提示,所以非常容易写错,中间少个标点符号空格啥的,调试起来太恶心了。 - 今天我写的,我能看懂,过几天我再来看,我自己都看不懂了,无可维护性!
如果你在日常组件开发时遇到类似的烦恼,那么好消息是,这是一个典型的使用css
变量的应用场景,教程传送门。
代码可维护性在整个项目中非常重要,不要为了赶进度或者偷懒而忽视。
使用css变量瘦身
现在,让我们把所有样式有关的东西通通留在css
代码里,本例中是两个颜色和一个饼图进度,那么相应的,我们要暴露出对应的css
变量让js
来操作。是的,css
代码就应该老老实实呆在css
里面,不要出来凑热闹.
修改上面的css
代码如下,定义需要暴露给js
的变量并赋予初始值:
#pie-chart {
/* 声明变量并初始化 */
--chartColor: orange; /* 背景色 */
--chartProgressColor: purple; /* 进度色 */
--chartProgress: 0%; /* 进度 */
width: 200px;
height: 200px;
border-radius: 100px;
/* 使用变量,(有点模板的意思) */
background-image: conic-gradient(
var(--chartProgressColor) var(--chartProgress),
var(--chartColor) var(--chartProgress)
);
margin-bottom: 24px;
}
然后在js
里直接操作css
变量即可,API传送门
<script type="text/javascript">
// 自定义颜色
const chartColor = '#C6E9FF'
const chartProgressColor = '#4589EF'
const elPieChart = document.getElementById('pie-chart')
const { style } = elPieChart
const elSlider = document.getElementById('slider')
// 首次渲染设置颜色
style.setProperty('--chartColor', chartColor)
style.setProperty('--chartProgressColor', chartProgressColor)
elSlider.oninput = function updateChart() {
const { value } = elSlider
//更改饼图进度
style.setProperty('--chartColor', chartColor)
style.setProperty('--chartProgressColor', chartProgressColor)
style.setProperty('--chartProgress', `${value}%`)
}
</script>
现在我们用更优,可读性更高的变量代替传统css
拼接字符串,经过优化后的js
代码更加js
.
你可以用喜欢的方式继续重构,那么上述操作css
变量的部分其实可以再优化,可以写工具类,但是无论如何,终于摆脱了css
.
试想,如果我们的组件dom
层级很深,还按照老的笨方法,层层查找节点,样式穿透,将会是噩梦,使用css
变量,只需专注变量自身,而无需考虑dom
层级,并且开发者可以更好维护,也方便了使用者通过css hack
的手段去定制样式,希望你能get到这个点。
更多场景
除了饼图,圆环进度条,Loading动画,遮罩等等也是锥形渐变的使用场景,大胆发挥你的想象力吧。
喜欢本文记得三连支持😙