CSS-纯 CSS 绘制三角形与扇形

30 阅读3分钟

前言

在前端开发中,有时我们需要一些非矩形的图形来增强页面的视觉效果,比如下拉菜单的小箭头、加载动画的扇形进度条。利用纯 CSS 绘制这些图形,不仅能减少图片请求,还能展示你对 CSS 底层渲染机制的深刻理解。

一、 纯 CSS 绘制三角形

1. 原理揭秘:Border 的“魔法”

当一个元素的 widthheight 都设置为 0 时,它的 border 属性就会呈现出奇特的几何形状:

image.png

.box {
  width: 0;
  height: 0;
  border: 50px solid;
  border-color: #96ceb4 #ffeead #d9534f #ffad60; /* 上右下左 */
}

如图所示,四条边框会形成四个三角形。要画出我们想要的三角形,只需将不需要的边框颜色设置为透明 transparent 即可。

2. 绘制向下三角形步骤

  1. 清空宽高:将元素的 widthheight 设置为 0
  2. 方向选择:确定三角形方向,例如要向下,则保留 border-top 的颜色,其他边设为透明。
  3. 控制大小border-width 决定三角形的腰长,而 border-color 不透明的那条边的宽度就是三角形的高度
.triangle-down {
  width: 0;
  height: 0;
  border-left: 25px solid transparent;    /* 左腰 */
  border-right: 25px solid transparent;   /* 右腰 */
  border-top: 50px solid #d9534f;        /* 底部,即三角形的“高” */
}

image.png


二、 纯 CSS 绘制扇形

绘制扇形的方法相对复杂,这里介绍两种常见思路。

核心知识点:

1. 思路一:基于三角形 + border-radius

如果你需要一个圆心角很小的扇形,可以在三角形的基础上,利用 border-radius 实现圆角效果。

  • border-radius :用于设置圆形的边角,设置的值为边角半径

    • 四个值分别为左上、右上、右下、左下(顺时针)
    • 三个值分别为左上、右上左下、右下(第二个值为第二个对角)
    • 两个值为左上右下、右上左下(两个对角)
    • 一个值为四周
  • clip:用于裁剪绝对定位的元素(元素属性必须为absolute、fixed)

    • clip的rect:接受四个值分别为top、right、bottom、left
    • top、right、bottom、left都是基于左上角来计算的
.sector-small {
  width: 0;
  height: 0;
  border-top: 50px solid blue;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-radius: 50px; /* 半径等于三角形的高 */
}

image.png

2. 思路二:利用半圆 + clip / transform (更通用)

这种方法可以绘制任意角度的扇形,尤其适用于进度条等场景。

  1. 画一个完整的圆border-radius: 50%

  2. 创建两个半圆遮罩:使用伪元素 ::before::after 或绝对定位的 div

  3. 核心技法

    • clip: rect(top, right, bottom, left) :用于裁剪绝对定位元素。它接受四个值,基于元素的左上角计算,用来裁剪出半圆。
    • transform: rotate() :旋转这些半圆,露出扇形区域。
<!DOCTYPE html>
<html>
  <body>
    <div class="container">
      <div class="pie-chart">
        <div class="left-half"></div>
        <div class="right-half"></div>
      </div>
    </div>

    <script></script>
  </body>

  <style>
    html,
    body {
      height: 100vh;
      margin: 0;
      padding: 0;
    }
    .container {
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .pie-chart {
      width: 200px;
      height: 200px;
      border-radius: 50%;
      background-color: aqua; /* 背景色作为扇形颜色 */
      position: relative;
      overflow: hidden; /* 隐藏溢出部分 */
    }

    /* 左半圆遮罩,通常初始设为遮挡 */
    .left-half {
      width: 200px;
      height: 200px;
      position: absolute;
      top: 0;
      left: 0;
      background-color: white; /* 遮罩色 */
      clip: rect(0px, 100px, 200px, 0px); /* 裁剪出左半部分 */
      transform-origin: center center; /* 旋转中心 */
      transform: rotate(-20deg);  /*动态旋转以露出扇形 */
    }

    /* 右半圆遮罩 */
    .right-half {
      width: 200px;
      height: 200px;
      position: absolute;
      top: 0;
      left: 0;
      background-color: white; /* 遮罩色 */
      clip: rect(0px, 200px, 200px, 100px); /* 裁剪出右半部分 */
      transform-origin: center center;
      transform: rotate(65deg);     /*  动态旋转以露出扇形 */
    }
  </style>
</html>