如何使用 CSS 创建有趣形状、字形和表情符号的图表

Avatar of Preethi
Preethi

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 $200 免费信用额度!

让我们放弃图表中常用的圆形和条形,转而使用更古怪的形状。随着在线演示越来越普遍,为您的网页幻灯片增添光彩并使其脱颖而出的捷径就是让图表焕然一新 🪄

我将向您展示如何使用字形、CSS 形状和表情符号创建有趣形状的图表,而且只需付出很少的努力。

让我们从一个简单的例子开始。

使用字形

<div id="chart">
  <div id="chart-shape">⬠</div>
  <div id="chart-value"></div> 
</div>
#chart {
  width: 300px; 
  height: 300px;
  display: grid;
  background: white;
}
#chart * {
  height: inherit;
  grid-area: 1 / 1;
}

我们首先为图表设置一些尺寸,并将两个 div 堆叠在其中,方法是将它们分配到同一个网格单元格中。也可以通过其他方式堆叠它们,例如使用 position 属性。

再次看一下上面的 HTML。其中一个 div 包含一个五角形符号,这是我们想要的图表形状。我使用“表情符号和符号”键盘添加了该符号,但也可以使用五角形的 HTML 实体值 &#x2B20; 在 div 中添加。

然后使用 CSS 字体属性以及所需的图表颜色对包含符号的 div 进行样式设置。它足够大且居中。

#chart-shape {
  font: 300px/300px serif;
  text-align: center; 
  color: limegreen;
}

HTML 中的第二个 div 包含一个圆锥形渐变背景图像。渐变的百分比表示图表的 **视觉值**。同一个 div 还包含 mix-blend-mode: screen;

#chart-value {
  background: conic-gradient(transparent 75%, darkseagreen 75%);
  mix-blend-mode: screen;
}

mix-blend-mode 属性将元素内部的颜色与其背景混合。screen 混合模式值会导致较浅的混合颜色透过来。在 darkseagreen 色圆锥形渐变与 limegreen 色五角星重叠的部分,较浅的绿色会透出来,而 darskseagreen 渐变的其余部分在图表的白色背景上会消失。

在 HTML 中添加图表形状的另一种方法是在 CSS 中将其添加为另一个背景层,并使用 background-blend-mode 而不是 mix-blend-mode。但是,CSS 中的图表形状代码可能不太容易一目了然。因此,您可以根据需要选择在 HTML 或 CSS 中添加图表形状,这两种方式都可以。

#chart {
  width: 300px; 
  height: 300px;
  background:
  url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='100%'><div xmlns='http://www.w3.org/1999/xhtml' style='font:300px/300px serif;color:limegreen;text-align: center;background:white'>⬠</div></foreignObject></svg>"),
  conic-gradient(transparent 75%, darkseagreen 75%);
  background-blend-mode: screen;
}

五角形符号作为背景图像被添加,除了圆锥形渐变以外。然后,background-blend-mode: screen; 属性值对生效,结果与之前的演示相同。

五角形背景图像是通过将包含五角形符号 () 的 HTML 嵌入到嵌入到数据 URL 中的 SVG 中来创建的。

<!-- Unwrapped SVG code from the Data URL -->
<svg xmlns='http://www.w3.org/2000/svg'>
  <foreignObject width='300px' height='100%'>
    <div xmlns='http://www.w3.org/1999/xhtml' 
         style='
          font:300px/300px serif;
          color:limegreen;
          text-align: center;
          background:white;'>
          ⬠
    </div>
  </foreignObject>
</svg>

在 CSS 中,这将变成以下内容:

background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='100%'><div xmlns='http://www.w3.org/1999/xhtml' style='font:300px/300px serif;color:limegreen;text-align: center;background:white'>⬠</div></foreignObject></svg>");

使用 CSS 形状

接下来,让我们使用 CSS 形状来代替符号。CSS 形状主要通过使用边框属性来创建。我们的存档中有一系列 CSS 形状 供您参考。

以下是一组属性,可以为我们稍后将添加到 SVG 中的元素创建一个简单的三角形形状,以替换符号

border: 150px solid white; 
border-bottom: 300px solid lime; 
border-top: unset;

与圆锥形渐变和背景混合结合使用后,结果如下:

<div id="chart"></div>
#chart {
  width: 300px;
  height: 300px;
  background:
  url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='100%'><html xmlns='http://www.w3.org/1999/xhtml'><div style='border:150px solid white; border-bottom:300px solid lime; border-top:unset'></div><div style='border:150px solid transparent; border-bottom:300px solid white; border-top:unset; transform:scale(0.8) translateY(-360px);'></div></html></foreignObject></svg>"),
  conic-gradient(transparent 75%, darkseagreen 75%);
  background-blend-mode: screen;
}

为了将设计限制在边框内,在设计中添加了一个较小的白色三角形。

<!-- Unwrapped SVG code from the Data URL -->
<svg xmlns='http://www.w3.org/2000/svg'>
  <foreignObject width='300px' height='100%'>
   <html xmlns='http://www.w3.org/1999/xhtml'>
    /* green triangle */
    <div style='
         border: 150px solid white; 
         border-bottom: 300px solid lime; 
         border-top: unset'></div>
    /* smaller white triangle */
    <div style='
         border: 150px solid transparent; 
         border-bottom: 300px solid white; 
         border-top: unset; 
         transform: scale(0.8) translateY(-360px);'></div>
   </html>
  </foreignObject>
</svg>

在 CSS 中,这将变成以下内容:

background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='100%'><html xmlns='http://www.w3.org/1999/xhtml'><div style='border:150px solid white; border-bottom:300px solid lime; border-top:unset'></div><div style='border:150px solid transparent; border-bottom:300px solid white; border-top:unset; transform:scale(0.8) translateY(-360px);'></div></html></foreignObject></svg>");

使用表情符号

表情符号可以与这种图表方法一起使用吗?当然可以!🥳

将一个块状颜色表情符号以与 HTML 符号相同的方式输入到 SVG 图像中。表情符号的块状颜色是通过为其指定一个透明的 color 值,然后添加所需的 text-shadow 颜色来创建的。我已经在 另一篇文章 中介绍过这种技术。

<div id="chart"></div>
#chart {
  width: 300px; 
  height: 300px;
  background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='300px'><body style='margin:0;text-align:center;color:transparent;' xmlns='http://www.w3.org/1999/xhtml'><div style='text-shadow: 0 0 limegreen;font:200px/300px serif;background:white;'>🍏</div><div style='text-shadow:0 0 white;font:170px/300px serif;position:relative;top:-300px;'>🍏</div></body></foreignObject></svg>"),
  conic-gradient(transparent 64%, darkseagreen 64%);
  background-blend-mode: screen;
}

与最后一个演示一样,在中心添加了一个较小的白色苹果形状,以创建边框设计。

<!-- Unwrapped SVG code from the Data URL -->
<svg xmlns='http://www.w3.org/2000/svg'>
  <foreignObject width='300px' height='300px'>
    <body xmlns='http://www.w3.org/1999/xhtml' style='
          margin: 0;
          text-align: center;
          color:transparent;'>
       /* green apple shape */
       <div style='
            text-shadow: 0 0 limegreen; 
            font-size: 200px; 
            background: white;'>🍏</div>
       /* smaller white apple shape */
       <div style='
            text-shadow:0 0 white; 
            font-size: 170px; 
            position: relative; 
            top: -300px;'>🍏</div>
    </body>
  </foreignObject>
</svg>

我将两个 div 添加到 <body> 元素中,这样 div 的重复样式属性只在 body 元素中声明一次。然后,div 将自动继承这些属性。

Chris 想出了一个想法,使用 CSS @property (在撰写本文时,Chrome 支持该特性) 对圆锥形渐变进行动画处理(更具体地说,是其百分比值),它对设计的影响非常美观。@property 是一个 CSS At-规则,它显式地定义了一个自定义 CSS 属性。在支持的浏览器中,使用 @property 定义的自定义属性可以进行动画处理。

@property --n {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 30%;
}
#chart {
  width: 300px; 
  height: 300px;
  --n: 30%;  /*declaration for browsers with no @property support */
  background: 
    url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='300px'><body style='margin:0;text-align:center;color:transparent;' xmlns='http://www.w3.org/1999/xhtml'><div style='text-shadow: 0 0 limegreen;font:200px/300px serif;background:white;'>🍏</div><div style='text-shadow:0 0 white;font:170px/300px serif;position:relative;top:-300px;'>🍏</div></body></foreignObject></svg>"),
    conic-gradient(transparent var(--n), darkseagreen var(--n));
  background-blend-mode: screen;
  transition: --n 2s ease-in-out	
}
#chart:hover { --n: 70%; }

上面的图表将在悬停时更改其值。在 Chrome 中,更改将看起来像是动画效果。

虽然效果不会像 CSS 动画那样流畅,但您也可以尝试使用 JavaScript 对渐变进行动画处理。以下 JavaScript 代码将使鼠标悬停在图表上时产生类似于上面的动画效果。

const chart = document.querySelector('#chart')
chart.onpointerover = ()=>{
  var i = 30,
      timer = setInterval(()=> {
        if (i < 70)
          chart.style.setProperty('--n', i++ + '%')
        else clearInterval(timer)
      }, 10)
}
chart.onpointerout = ()=>{
  var i = 70,
      timer = setInterval(()=> {
        if (i >= 30) 
          chart.style.setProperty('--n', i-- + '%')
        else clearInterval(timer)
      }, 10)
}

在尝试自己的设计时,请记住不同的混合模式是如何工作的。我在所有演示中都使用了 screen 混合模式,只是为了简化操作。但是,使用不同的混合模式和不同的背景颜色,您将获得不同的结果。因此,如果您还没有深入了解 混合模式,我建议您 深入了解 一下。

此外,如果您想从最终结果中排除元素的颜色,请尝试在元素上使用 isolation: isolate; — 浏览器在应用混合时会忽略该背景颜色。

即使我们可以使用各种奇形怪状的形状,并用我们想要的任何鲜艳的颜色进行装饰,也要始终注意可读性,确保图表值足够大且清晰易读。