前端开发者学堂 - fedev.cn

CSS vs SVG: 最后一节(上部分)

发布于 大漠

这是CSS技术和SVG技术对比系列教程中最后一篇。本文选取了几个CSS和SVG的解决方案,而不是一个解决方案——使用CSS和SVG实现。有关于解决方案的每个细节已经有很多这方面的优秀文章,如果你感兴趣的话,可以阅读有关于这个系列的所有文章

让我们先从CSS和SVG最具争议的主题开始:图标系统。

字体图标 VS. SVG图标

在我的印象中,我个人使用字体图标只用过两次,都是在客户端项目中使用的。我从来不觉得他们直观。

使用字体图标不具语义化:一个图标是一个图像或数字,而且字体图标一般都使用空的<div><span>标签,配合伪元素的content属性。

字体图标是单色的,不能实现多色图标,除非你使用多个元素拼合在起,然后为每个形状使用不同的颜色,从而构成一个完整的图标。虽然想出这个解决方案的人来说很聪明,但略显多余,至少我是这样看的。如果你对这个解决方案感兴趣,可以看看Parker Bennett写的一篇博文,这篇文章就是介绍如何通过多个元素构建一个彩色的图标。

扩展阅读

字体图标在很多浏览器上也会奇怪的失败、有锯齿等问题,常常要用反锯齿样式让他们看起来不那么锋利,这是多么令人烦恼的一件事情。

Chris Coyier在CSS-Tricks上专门写了一篇有关于字体图标和SVG图标之间的利弊,以及CSS怎么来显示。如果你对此感兴趣,可以点击这里阅读(中文译文可以点这里)。

这里总结了一些有关于SVG图标的优点:

  • SVG更具语义化,SVG图标就是一个图标标记
  • SVG在所有屏幕分辨率下都能渲染的清晰,看起来干净利落
  • SVG图标能更好的控制图标样式(比如说彩色图标)。可以选择在SVG中设置或使用CSS样式来控制。当然有一些限制,看取决于你是如何嵌入SVG,但这将来或许会有所改变。(我在Codrops上写了一篇有关于这方面的文章)
  • SVG图标还可以做动画交互效果。图标改变形状时可以具有动画效果
  • 你可以使用PNG图为SVG图标作降级处理,让不兼容SVG的浏览器能显示PNG图标
  • SVG图标具有较好的浏览器兼容性,在支持SVG的浏览器下能显示出一样的效果
  • SVG更易创建、嵌入和维护
  • SVG更具可访问性。SVG带有可访问性元素,改善其内容的可访问性。你可以在这里了解更多有关于这方面的知识。

有几种方法可以使用SVG Sprites创建SVG图标系统,让浏览器支持变得更具可靠性。在使用这种技术时,还有一两个Bug。不过我强烈建议你阅读这方面的文章,甚至可以尝试一下。

扩展阅读

图表

引入新的技术来创建图表, 这变得更佳有趣。下面我们深入来看看。

CSS制作图表

使用CSS创建的普通矩形和圆形等形状,可以创建一些简单的图表。

因为CSS创建矩形是非常强大的,只使用CSS来制作图表,最好的一个示例就是创建水平或垂直的矩形图表。

Eric Meyer在很久以前就使用CSS创建了竖线的概述图效果。在他的这篇文章中,他解释了如何使用CSS创建条形图形和使用一个HTML的<table>元素来给图表标记数据。Eric Meyer介绍的技术是强大的,因为数据采用了语义化的标签来标记(<table>用来存储数据,可谓是最完美的方式),而且数据可以使用服务端动态插入,比如说PHP语言。

Robin Rendle在Eric的技术上创建一了种新的条形图表,他们使用了相同的原则和CSS技巧。下面的标记就是来自于Robin Rendle的文章:

<table id="q-graph">
    <caption>Quarterly Results</caption>
    <thead>
        <tr>
         <th></th>
            <th class="sent">Invoiced</th>
            <th class="paid">Collected</th>
        </tr>
    </thead>
    <tbody>
        <tr class="qtr" id="q1">
        <th scope="row">Q1</th>
        <td class="sent bar"><p>$18,450.00</p></td>
        <td class="paid bar"><p>$16,500.00</p></td>
    </tr>
        <tr class="qtr" id="q2">
        <th scope="row">Q2</th>
        <td class="sent bar"><p>$34,340.72</p></td>
        <td class="paid bar"><p>$32,340.72</p></td>
    </tr>
    <tr class="qtr" id="q3">
        <th scope="row">Q3</th>
        <td class="sent bar"><p>$43,145.52</p></td>
        <td class="paid bar"><p>$32,225.52</p></td>
    </tr>
    <tr class="qtr" id="q4">
        <th scope="row">Q4</th>
        <td class="sent bar"><p>$18,415.96</p></td>
        <td class="paid bar"><p>$32,425.00</p></td>
    </tr>
    </tbody>
</table>

使用CSS给表格单元格定位之后,你最终可以看到下图的效果:

CSS制作图表

具体示例如下:

在他的文章中,Robin还使用相同的原则,创建迷你图表,具本的细节,可以阅读相关文章

前面介绍的都是使用CSS创建矩形的柱形图表,其实CSS也可以创建饼图。

Lea Verou在CSS技术上具有极高的水平,也想了一个聪明的方式,使用伪元素来和CSS的旋转来创建 两色的饼图。在这篇文章中她详细介绍了有关于这方面的技术。

CSS制作双色饼图

使用伪元素和CSS的transform创建一个饼图。上图中虚线的矩形就是伪元素在其父容器中做圆形旋转。

Lea的技术能让你创建像上图所示的双色饼图效果,但是,如果要创建更多颜色的饼图就不是那么容易的事情了。

借Lea的一篇文章来做介绍,使用conic-gradient可以实现多色饼图。具体如何实现,本文不做过多阐述,如果你对这方面的技术感兴趣,你可以看看Lea写的相关教程

多色饼图

上图就是conical-gradient的一个示例截图。另外提供@一丝姐姐下面的案例:

使用conical-gradient,你想要多少颜色的饼图都可以创建。

此外,一旦attr()函数在CSS Values Level 3得到广泛支持,将来只要在一个HTML元素上控制其百分比就可以实现多色饼图: background: conic-gradient(#655 attr(data-value %), yellow green 0); 另外可以使用下面的方法来实现三中颜色的饼图,也是较为容易 background: conic-gradient(deeppink 20%, #fb3 0, #fb3 30%, yellowgreen 0); —Lea Verou

尽管浏览器现在还不支持conic-gradient属性,但Lea写了一个Polypill库,你现在就可以使用他们。如果你感兴趣的话,一定要自己动手尝试一下。

尽管使用CSS也可能制作出折线图,但我强烈反对使用,因为他们既不方便而且也不是一个表示数据的好方法。

扩展阅读

SVG图表

当涉及到创建图表和数据可视化时,SVG胜过其他技术,包括CSS。

SVG图表和数据可视化访问可以充分互动。SVG不规则的形状是一个完美的效果,而且数据可视化效果可以通过这些不规则形状更好的展示出来。

HTML5 Canvas也可以用来做数据可视化,但是Canvas不是DOM的一部分,因此屏幕阅读器无法访问。你需要在<canvas>标签中创建一个备用访问内容。你需要采用额外的措施将内容映射到画布上,这样屏幕阅读器才能知道元素之间的相互作用。所以一个HTML5 Canvas需要维护双倍的数据。

使用SVG,语义化强和更具可访问性,而且可以结合JavaScript做交互效果。

条形图可以很容易的使用SVG的<rect><line>实现,而数据也可以使用<text>元素,而不需要为内容另外准备一张图。

然而,你可能会不想手动创建这些图表,特别是复杂的数据图表,或者需要动态的交互效果的图表。这个时候你就可以使用D3.js这样的框架了。

d3.js

D3是Data-Driven Documents的简写。是一个数据可视化的JavaScript库。D3可以帮助你使用HTML、SVG和CSS将数据完整的在现代浏览器展示。

D3可能是最受欢迎的数据可视化操作的一个库,有大量的文章和书介绍如何使用D3。这里有些资源供你参考:

当你使用SVG创建一个简单的饼图时,不需要使用D3这样的库,特别是你的饼图是简单的、静态的,而不是动态的。

Lea在Smashing Magazine上有一篇文章详细介绍 了SVG技术和CSS技术创建一饼图的对比,而且她还想出了一个更实用的SVG技术。使用SVG中的heavy/thick描边来做圆形。

下图展示了如何使用SVG中的strokestroke-dasharray属性实现的饼图效果过程:

SVG饼图

配合一些JavaScript,你可以动态的看到stroke创建饼图的整个过程。有关于详细的介绍可以阅读Lea写的文章

Robin Rendle也在CSS-Tricks上写过一篇使用SVG创建图给的文章。

折线图,地图等,都可以使用SVG来创建。SVG将成为制作数据可视化的最佳工具,也可以做出很多好看的图表

话又说回来,你可能想避免使用SVG、HTML5 Canvas或者WebGL来制作复杂的数据可视化图表,那么你将需要使用成千上面的DOM元素,而且这种情况下制作也是非常的麻烦。至少到现在很少有人会这样去做。另外SVG制作超复杂的数据可视化图表时,需要很多的DOM节点,在这样的场景之下,HTML5 Canvas的性能要比SVG性能略强一些。所以你应该在合适的场景使用合适的技术,做出明智的选择。

Elastic UI互动

在一些地方,CSS不能像SVG一样创建不规则的UI形状和动画,这或许也是SVG最强大特性之一。

下面的示例是@Mary Lou在Codrops写的一个幻灯片的效果:

SVG动画示例

幻灯片使用了SVG的path,并且给播放幻灯片时添加了一个路径动画效果。

下图展示了动画中用到的三个路径形状:

SVG动画

使用JavaScript,你可以定义这些路径形状:

// …
 // path definitions
    paths : {
        rect : ‘M33,0h41c0,0,0,9.871,0,29.871C74,49.871,74,60,74,60H32.666h-0.125H6c0,0,0-10,0-30S6,0,6,0H33’,
        curve : { 
            right : ‘M33,0h41c0,0,5,9.871,5,29.871C79,49.871,74,60,74,60H32.666h-0.125H6c0,0,5-10,5-30S6,0,6,0H33’, 
            left : ‘M33,0h41c0,0-5,9.871-5,29.871C69,49.871,74,60,74,60H32.666h-0.125H6c0,0-5-10-5-30S6,0,6,0H33’
        }
    }
//…

至于动画效果,你可以使用Snap.svg这样的库,幻灯片动画效果选择的是:

// change svg path on entering slide to "curved"
    var currItem = this.items[ this.curr ];
    currItem.querySelector('path').setAttribute( 'd', dir === 'right' ? pathCurvedLeft : pathCurvedRight );
    
    // morph svg path on entering slide to "rectangle"
    setTimeout(function() { currItem.path.stop().animate( { 'path' : pathRectangle }, speed * 3, mina.elastic ); }, speed * .5 );

上面的代码只是部分演示如何简单定义动画路径,如果你要完整的看到示例的效果,要确保你的代码是完整的。

有人可能会认为,上面的效果应该使用CSS。但是,就算CSS的clip-path可以裁剪出不规则的形状(正如我们在前一篇文章中介绍的一样),他们目前仍依赖于SVG创建复杂的形状。所以上面的示例中的形状,不可能使用的是CSS。

我们来看@Mary Lou写的第二个示例:

SVG动画

点击按钮时侧边栏菜单的边框有一个弹性的效果,到目前为止还无法在CSS中画一条这样的线。

在Codepen上能找到很多有趣的SVG动效果案例,下面展示的效果就和上图有点类似:

其他动画效果

尽管使用CSS的filter()可以创建一些特定的效果,但是SVG的内置filter具有更多的功能,可以做出更复杂的效果,而且做出来的效果非常吸引人。

Lucas Bebber一直致力于SVG制作的神奇效果。比如他在Codrops上分享的一个动动模糊的案例:

SVG动画

Gooey Effect是SVG中使用filter属性制作的最有吸引的效果,如下所示:

Lucas在CSS-Tricks上写了一篇文章,一步一步的告诉你如何创建这个效果,并且在Codrops还创建了一个根据音乐频率改变粘性的动画效果

这些效果展示了SVG的能力,以及告诉我们如何做出更有趣的UI交互效果。我强列建议您看看Lucas在Codepen上写的有关于SVG的案例,你会受益良多。

总结

我们绝对没有涵盖所有内容,本文只是讨论了一些入门级别的概念,但我希望这个系列能让你更清的知道如何使用SVG来解决和改善我们设计中常见的一些问题,或者为这些设计提个一个更合理的,更适当的解决方案。

有的时候,有些设计方案使用SVG能做得比CSS更好,这也不可争的事实。然而,并没有说过SVG将替代CSS。应该说SVG和CSS是一个强大的组合,这个组合能让我们把静态的UI提高一个层次,进入一个全新的水平。

我希望你喜欢这个系列,更希望这个系列对你有所帮助。

本文根据@Sara Soueidan的《CSS vs SVG: The Final Round(up)》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://blogs.adobe.com/dreamweaver/2015/09/css-vs-svg-the-final-roundup.html