我应该使用 CSS 还是 SVG 来显示形状?

Posted

技术标签:

【中文标题】我应该使用 CSS 还是 SVG 来显示形状?【英文标题】:Should I use CSS or SVG's for displaying shapes? 【发布时间】:2016-09-30 04:16:09 【问题描述】:

我一直在使用 CSS 在我的网站中处理形状,这一切都很好,但有时在操作它们时有点烦人,因为例如三角形,它实际上是一个带边框的矩形。

关于在 CSS 中创建形状的指南,我使用的是 CSS-tricks article。

我想使用 CSS,因为它的加载速度比我使用图像时要快。

几天过去了,我偶然发现了 SVG,我一直在网上看到它们,但从未深入研究过它们。所以,我想知道,使用 SVG 而不是这些 CSS 'hacks' 来实现我的形状会更简单吗?找不到有关此特定主题的任何脏信息,因此感谢您提供有关 SVG 的任何信息。 (这些形状的宽度将超过 1000 像素,因此我不想使用图像...)

TL;DR:什么更好 - 跨浏览器/加载时间 - 当想要在网页上具有形状时。我只是研究了 SVG,想知道它是否是一个可行的选择。


编辑

对不起,下面是我目前用来实现效果的代码,以及我想要实现的图像(不幸的是,设计图像的人没有提供设计代码,只有图片)。

源图片

我的代码 (对不起,如果你不喜欢 sass)

<div class="arrow-wrap">
  <div class="arrow">
    <div class="arrow-text">
      <h1>Services</h1>
      <p>Learn more about our services by selecting one below</p>
    </div>
  </div>
</div>

.arrow-wrap
    overflow: hidden;
    display: flex
    justify-content: center
    position: relative
    z-index: 10
    .arrow
        width: 0
        height: 0
        border-style: solid
        border-width: 150px 100vw 0 100vw
        border-color: $dark transparent transparent transparent
        position: relative
        z-index: 1
        display: flex
        justify-content: center
        .arrow-text
            text-align: center
            margin-top: -130px
            white-space: nowrap
            position: relative
            z-index: 5
            h1
                font-size: 50px
                margin: 0
            p
                margin: 0
                color: rgba($white, 0.8)

我的结果图片

所以,因为我不得不到处乱搞才能让文本工作(缩放仍然不完美),我想知道是否采用 SVG 的路线,也就是说,如果 SVG 是在完成工作/加载时间方面更有效率。


编辑 2

我也只是在想——给顶部增加更多空间——添加一个实心盒子阴影来创造一种不规则五边形的错觉(Found on YouTube here)

【问题讨论】:

SVG 将允许您根据需要创建复杂的形状,它是一种矢量图像格式,而不是样式描述。 CSS 将允许您使用技巧创建简单的形状(嗯,不是真的,它将样式化 html 元素以类似于某些形状)。所以,如果你只需要简单的形状就用 CSS,如果你需要复杂的形状就用 SVG。 【参考方案1】:

所以回答原来的问题:

如果您正在考虑将数据从 http 服务器传输到连接客户端的时间,那么 CSS 显示形状的速度要快得多,只要形状是简单的图形,没有动画并且不包含自定义曲率或路径或多层。

SVG 主要是用于制作动画和复杂艺术品的工具。

基本上有两种方法可以渲染更复杂的动画和绘图(我的意思是在网页上的俄罗斯方块游戏中复杂)

您可以使用 SVG 或 CANVAS。 (还有其他 3rd 方插件,如Shockwave/flash 等)

但基本上,Canvas 是 SVG 的更易于使用的替代品,原因之一是:它的 javascript 友好。您可以使用 Javascript 在 Canvas 上动态绘制。

您也可以使用 Javascript 绘制 SVG 内联元素,但如果没有 SVG.JS 或 SNAP.JS 等额外的 javascript 库,它就不那么简单了

另一方面,SVG 比画布更容易缩放到不同的尺寸。您可以简单地更改 SVG 元素的视口并获得已缩放的图像。 HTML5 画布可能更令人沮丧,无法缩放到正确的尺寸。

CSS 的优点是在加载方面更轻量级和更快,但是要执行复杂的多层动画和其他事情(例如图层蒙版/着色器效果)要困难得多,因为您必须手动计算所有简单的几何而不是让计算机来做。

话虽如此,您可以在 SVG、CSS 和 HTML5 CANVAS 之间进行选择来呈现您的图像。大多数优秀的网页都结合了这三者,因为有些网页在不同方面优于其他网页。

我在下面附上了一个示例,说明如何使用您提供的代码以及 HTML5 Canvas 来动态创建形状。

.arrow-wrap: 
  overflow: hidden;
  display: flex justify-content: center position: relative z-index: 10

.arrow: 
  width: 0 height: 0 border-style: solid border-width: 150px 100vw 0 100vw border-color: $dark transparent transparent transparent position: relative z-index: 1 display: flex justify-content: center

.arrow-text: 
  text-align: center margin-top: -130px white-space: nowrap position: relative z-index: 5

h1: 
  font-size: 50px margin: 0

p: 
  margin: 0 color: rgba($white, 0.8)

</style
<!DOCTYPE HTML>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">


</head>

<body>
  <div class="arrow-wrap">
    <div>
      <div class="arrow-text">
        <h1 class="arrow">Services</h1>



        <p>Learn more about our services by selecting one below</p>
      </div>

    </div>
    <div class="arrow"><a href="#">My Service 1</a>
    </div>
    <div class="arrow"><a href="#">Service 2</a>
    </div>

  </div>
</body>

<script>
  var canv_active_id = 0;
  // find al elements of arrow class
  var x = document.getElementsByClassName("arrow");
  var i;
  for (i = 0; i < x.length; i++) 
    // create a canvas element with uniqueID
    var canv = document.createElement('canvas');
    canv.id = "canvas" + canv_active_id;
    canv.width = 21;
    canv.height = 24;
    canv.style.width = x[i].innerWidth * 0.05;
    canv.style.height = x[i].innerHeight * 0.55;

    //place the canvas element at the start of 
    //element
    var old_html = x[i].innerHTML;
    x[i].innerHTML = "";

    x[i].appendChild(canv);

    x[i].innerHTML += old_html;

    // get canvas context
    var ctx = document.getElementById("canvas" + canv_active_id).getContext('2d');
    // setup viewport
    ctx.scale(canv.style.width, x[i].innerHeight);

    ctx.save();
    ctx.transform(1.000000, 0.000000, 0.000000, 1.000000, -126.526770, -266.500710);


    // perform drawing by using lineTo()
    // #path4138
    ctx.beginPath();
    ctx.globalAlpha = 0.7;
    ctx.miterLimit = 8.19999981;
    ctx.lineWidth = 1.000000;
    ctx.fillStyle = 'rgba(215, 238, 244, 0.7)';
    ctx.moveTo(126.526770, 266.500710);
    ctx.lineTo(137.339480, 271.799980);
    ctx.lineTo(148.152170, 277.099260);
    ctx.lineTo(137.408870, 284.043060);
    ctx.lineTo(126.665560, 290.986860);
    ctx.lineTo(126.596160, 278.743780);
    ctx.fill();
    ctx.restore();

    //increase unique ID
    canv_active_id++;
  
</script>



</html>

如果您要拥有大量形状,CANVAS 可能是您要走的路,那么它也可能不是。您必须根据页面内容做出决定。

【讨论】:

添加了更多内容供您查看。到目前为止有用的信息,谢谢。【参考方案2】:

两者都用。

CSS

对基本形状使用 CSS。基本动画。就像您在使用 CSS 生成自定义形状时提到的那样,您所做的只是添加框阴影的边框来创建您想要的形状的错觉。有些人可能会说这不是未来的证据,并且可能会因任何更新而中断。

SVG

将 SVG 用于更复杂的形状和动画。根据您实现 SVG 的方式,您可以做某些事情。您可以直接嵌入它们,也可以通过 HTML img 标签嵌入它们,甚至可以使用 javascript 库将它们注入到您的应用程序中。

SVG 可以通过操纵 svg 本身的样式来制作动画,但这(取决于您的目标)可能会变成一个非常深的兔子洞。我对 SVG 动画的建议是使用 javascript 库。

我的建议是两者都用。首先感受一下 CSS。对我来说,如果您想要快速获得东西,这条路线似乎不那么受阻并且最容易学习。也可以试试 SVG 我过去使用 SVG 库创建了一些很棒的效果,这些东西单独使用 CSS 是不可能的,它们甚至可以在 IE9 中工作(不再支持它)。

TLDR;

将 CSS 用于基本形状和动画

将 SVG 用于高级形状和动画。

【讨论】:

我想补充一点,用 css 制作的动画是由浏览器的另一个线程处理的,所以它们不会因为 cpu 负载而减慢,而 svg 是。 @Alessandro_russo 你应该看看网络工作者这可能使用它们developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/…

以上是关于我应该使用 CSS 还是 SVG 来显示形状?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SVG 形状进行图像剪辑?

svg 剪辑图像并显示中风

创建一个反向剪辑路径 - CSS或SVG

创建反向剪辑路径 - CSS 或 SVG

SVG绘图 - 动画后形状消失[重复]

如何在 CSS 中创建这种形状(带圆角的四边形)?