CSS `conic-gradient` 实现饼图、环形进度条与复杂图案

各位观众老爷们,今天咱们来聊聊CSS里一个挺有意思的家伙——conic-gradient,也就是圆锥渐变。别看名字挺唬人,其实用起来特别灵活,能搞出各种饼图、环形进度条,甚至一些复杂的图案,绝对是CSS界的万金油选手。

一、conic-gradient:初次见面,请多关照

首先,咱们得认识一下这位主角。conic-gradient顾名思义,就是一种从圆心发散的渐变。它的基本语法长这样:

background: conic-gradient([from angle] [at position,] color stop list);

看着是不是有点眼晕?别慌,咱们慢慢拆解:

  • from angle 可选项,指定渐变起始的角度。默认是0度,也就是从正上方开始。你可以用from 90deg让渐变从右边开始。
  • at position 可选项,指定渐变圆心的位置。默认是center,也就是元素的中心点。你可以用at top left让圆心跑到左上角。
  • color stop list 必须项,指定颜色和位置。就像线性渐变一样,你可以设置多个颜色和它们的位置,用逗号分隔。

举个例子,一个简单的红绿蓝圆锥渐变:

.example {
  width: 200px;
  height: 200px;
  border-radius: 50%; /* 让它变成圆形 */
  background: conic-gradient(red, green, blue);
}

这段代码会创建一个红绿蓝的圆形渐变,默认从顶部开始,颜色均匀分布。

二、饼图:吃货的福音

现在,咱们开始玩点高级的。用conic-gradient做饼图简直不要太简单。核心思路就是利用颜色停止点来划分扇形区域。

假设我们要做一个表示数据占比的饼图,数据如下:

数据项 数值
A 30
B 50
C 20

首先,我们需要把数值转换成百分比:

  • A: 30%
  • B: 50%
  • C: 20%

然后,把百分比转换成角度(因为一个圆是360度):

  • A: 30% * 360 = 108度
  • B: 50% * 360 = 180度
  • C: 20% * 360 = 72度

有了角度,就可以写CSS了:

.pie-chart {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background: conic-gradient(
    red 0deg,
    red 108deg,
    green 108deg,
    green 288deg,
    blue 288deg,
    blue 360deg
  );
}

这段代码的关键在于颜色停止点的设置。每个颜色都要定义两个停止点:一个表示扇形的起始位置,一个表示扇形的结束位置。

  • 红色从0度开始,到108度结束。
  • 绿色从108度开始,到288度结束(108 + 180 = 288)。
  • 蓝色从288度开始,到360度结束(288 + 72 = 360)。

这样就得到了一个简单的饼图。当然,实际应用中,你肯定需要动态计算角度,并用JavaScript来生成CSS代码。

三、环形进度条:装逼利器

环形进度条比饼图稍微复杂一点,但原理类似。核心思路是:用一个颜色表示进度,另一个颜色表示剩余部分。

.progress-ring {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background: conic-gradient(
    red 70%,  /* 红色表示70%的进度 */
    lightgray 0  /* 浅灰色表示剩余的30% */
  );
}

这段代码会创建一个红色进度条,进度为70%。lightgray 0表示从70%的位置开始,使用浅灰色填充剩余部分。

但是,这样写出来的进度条是“实心”的,没有环形的效果。要实现环形,我们需要用到一个CSS技巧:mask或者clip-path。这里我们用clip-path,因为兼容性更好。

首先,创建一个圆形遮罩:

.progress-ring {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background: conic-gradient(
    red 70%,
    lightgray 0
  );
  clip-path: circle(50%); /* 裁剪成圆形 */
}

然后,在内部再创建一个更小的圆形,盖住中间的部分:

<div class="progress-ring">
  <div class="progress-ring-inner"></div>
</div>
.progress-ring {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background: conic-gradient(
    red 70%,
    lightgray 0
  );
  clip-path: circle(50%);
  position: relative; /* 让内部元素可以绝对定位 */
}

.progress-ring-inner {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%); /* 居中 */
  width: 120px; /* 比外层小 */
  height: 120px;
  border-radius: 50%;
  background-color: white; /* 填充白色 */
}

这段代码的关键在于内部元素的尺寸要小于外部元素,并且背景色要和页面背景色一致,这样才能“挖”出一个环形。

最后,为了让进度条动起来,我们可以用CSS动画:

.progress-ring {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background: conic-gradient(
    red 0,
    red var(--progress), /* 使用CSS变量控制进度 */
    lightgray 0
  );
  clip-path: circle(50%);
  position: relative;
  animation: rotate 1.5s linear forwards; /* 添加旋转动画 */
}

.progress-ring-inner {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 120px;
  height: 120px;
  border-radius: 50%;
  background-color: white;
}

@keyframes rotate {
    to {
        transform: translate(-50%, -50%) rotate(360deg);
    }
}
// JavaScript代码,用于动态设置进度
const ring = document.querySelector('.progress-ring');
ring.style.setProperty('--progress', '70%'); // 设置进度为70%

这里我们使用了CSS变量--progress来控制进度,方便用JavaScript动态修改。

四、复杂图案:脑洞有多大,舞台就有多大

conic-gradient的强大之处在于它可以创造各种复杂的图案。只要你脑洞够大,就能用它画出各种奇奇怪怪的东西。

比如,我们可以用它画一个棋盘:

.chessboard {
  width: 200px;
  height: 200px;
  background: conic-gradient(
    white 0deg 45deg,
    black 45deg 90deg,
    white 90deg 135deg,
    black 135deg 180deg,
    white 180deg 225deg,
    black 225deg 270deg,
    white 270deg 315deg,
    black 315deg 360deg
  );
  background-size: 50% 50%; /* 缩小背景,形成棋盘格子 */
}

这段代码的核心在于background-size属性。通过缩小背景图片,我们可以让渐变重复,从而形成棋盘的格子。

再比如,我们可以用它画一个雷达图:

.radar-chart {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background:
    conic-gradient(
      rgba(0, 255, 0, 0.5) 0deg,
      rgba(0, 255, 0, 0.5) 270deg,
      transparent 270deg
    ),
    repeating-radial-gradient(
      circle,
      rgba(0, 0, 0, 0.1) 0,
      rgba(0, 0, 0, 0.1) 10px,
      transparent 10px,
      transparent 20px
    );
}

这段代码使用了conic-gradientrepeating-radial-gradient两种渐变,叠加在一起,形成雷达图的效果。

五、兼容性:老铁,没毛病

conic-gradient的兼容性还算不错。主流浏览器都支持,但IE浏览器就别想了。

浏览器 版本 支持情况
Chrome 69+ 支持
Firefox 60+ 支持
Safari 12.1+ 支持
Edge 79+ 支持
Opera 56+ 支持
IE 不支持

如果你需要兼容IE,那就只能用图片或者SVG来实现了。

六、总结:渐变的世界,无限可能

conic-gradient是一个非常强大的CSS属性,可以用来创建各种各样的图形和效果。只要你掌握了它的基本语法和原理,就可以发挥你的想象力,创造出更多有趣的东西。

今天的讲座就到这里,希望大家有所收获。记住,学无止境,多动手实践才是王道!下次有机会再和大家分享更多CSS技巧。拜拜!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注