SVG到底是个啥?

2,296 阅读5分钟

为啥要学SVG,背景图不香吗?

SVG高深莫测,Canvas讳莫如深,只有background-image才是永远滴神。相信大多数刚从事前端行业的同学,在遇到CSS+DIV搞不定的展示效果时,都会选择直接使用切图来直接作为元素背景使用,对于SVG摸不着头脑的命令和Canvas晦涩难懂的语法都会选择视而不见。

无疑,切图当做背景是开发效率最高的方案,但是相信我,当你掌握了SVGCanvas的要领之后,在面对一些异型图案和复杂动画场景时,你会更从容再也不会体验到黔驴技穷时的窘迫。毕竟,某些场景下,SVGCanvas就是所有选择中的最优解。

Canvas暂且不表,今天我们就来扒一扒SVG看似生人勿进的高冷外衣。

SVG到底是个啥?

关于这个问题,让我们先来看看MDN上的定义:

可缩放矢量图形Scalable Vector Graphics,SVG),是一种用于描述二维的矢量图形,基于 XML 的标记语言。作为一个基于文本的开放网络标准,SVG 能够优雅而简洁地渲染不同大小的图形,并和CSSDOMJavaScriptSMIL等其他网络标准无缝衔接。本质上,SVG 相对于图像,就好比 HTML 相对于文本。 和传统的点阵图像模式,像JPEGPNG不同,SVG 格式提供的是矢量图,这意味着它的图像能够被无限放大而不失真或降低质量,并且可以方便地修改内容。

不知道冗长的定义是否把大家绕晕了,简单总结一下就是:

SVG是可以让图片无限放大都不会失真的一种基于XML的标记语言。

其实,SVG作为和CSS同时期的产物,如今并不如CSS的人尽皆知也是有历史原因的。

在早期的前端领域,CSS+DIV属于一家独大的统治地位,这主要源于早期的Web主要以图文展示为主,而更擅长图形展示的SVG只能偃旗息鼓无人问津。

不过,随着网络的发展、带宽的增加、flash的消亡、屏幕的丰富、审美的提高等等原因,有着正牌血统和标准化规范的SVG也就顺势崛起,与此同时也顺道开启了丰富多彩百家争鸣的视觉效果大内卷时代。

SVG能做什么?

现在我们知道了SVG是什么,那么它又能做什么呢?

这是个大问题,要真想讲明白可能真能说上好多,不过,我倒是真的想说上一说,在回答问题之前,不妨让我们把问题适度拆解一下:

  1. SVG基础用法
  2. SVG擅长些啥?
  3. SVG不擅长些啥?
  4. SVG的奇淫巧技

带着这个问题的疑问,让我们一点点的走进SVG的世界。

SVG的基础用法

相信我,学习枯燥的语法知识最快的途径就现学现用,今天我们只把SVG常用标签做为一个图鉴来速览一遍,先建立宏观的知识图谱再回头深究用法和原理,不需要死记硬背多看多体会,如果你能看到这个系列的最后,说不定还能无师自通呢。

矩形 <rect>

1.png

<svg width="200" height="100" viewBox="0 0 220 100" xmlns="http://www.w3.org/2000/svg">
    <-- 直角矩形 --> 
    <rect x="10" y="25" width="100" height="50"/>
    <-- 圆角矩形 -->
    <rect x="120" y="25" width="100" height="50" rx="15" ry="15"/>
</svg>

圆形 <circle>

2.png

<svg width="100" height="100" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg">
    <circle cx="60" cy="60" r="50"/>
</svg>

椭圆 <ellipse>

3.png

<svg width="200" height="100" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg">
    <ellipse cx="60" cy="60" rx="100" ry="50" />
</svg>

多边形 <polygon>

4.png

<svg width="200" height="100" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
    <polygon points="50,10 150,10 190,90 10,90" fill="none" stroke="black"/>
</svg>

多线段 <polyline>

5.png

<svg width="200" height="100" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
   <polyline points="50,10 150,10 190,90 10,90" fill="none" stroke="black"/>
</svg>

注意:与十分相似,只不过形成的是闭合形状,形成的是开放形状.

线段 <line>

6.png

<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <line x1="0" y1="0" x2="100" y2="100" stroke="black" />
</svg>

路径 <path>

7.png

<svg width="100" height="100"viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <path d="M 10,30
             A 20,20 0,0,1 50,30
             A 20,20 0,0,1 90,30
             Q 90,60 50,90
             Q 10,60 10,30 z"/>
  </svg>

path这里必须要重点说说,path可以被称之为SVG中的最强元素,几乎所有的二维形状(包括上述所有元素形状)都可以通过path来创建,而且path中的命令也是所有SVG元素中最多的。

文字 <text>

8.png

<svg width="200" height="100" viewBox="0 0 150 100" xmlns="http://www.w3.org/2000/svg">
    <style>
      .small { font: italic 13px sans-serif; }
      .heavy { font: bold 30px sans-serif; }
      .Rrrrr { font: italic 40px serif; fill: red; }
    </style>

    <text x="20" y="50" class="small">Test</text>
    <text x="40" y="50" class="heavy">SVG</text>
    <text x="55" y="75" class="small">Text</text>
    <text x="65" y="75" class="Rrrrr">Tag</text>
</svg>

裁剪 <clip-path>

9.png

<svg width="100" height="100" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg">
    <defs> 
        <clippath id="clipCircle"> 
            <circle cx="50" cy="60" r="50" />
        </clippath> 
    </defs> 
    <circle cx="75" cy="60" r="50" clip-path="url(#clipCircle)"/>
  </svg>

蒙版 <mask>

10.png

<svg width="100" height="100" viewBox="-10 -10 120 120">
    <mask id="myMask">
      <rect x="0" y="0" width="100" height="100" fill="white" />
  
      <path d="M10,35 A20,20,0,0,1,50,35
               A20,20,0,0,1,90,35 Q90,65,50,95
               Q10,65,10,35 Z" fill="black" />
    </mask>
    <circle cx="50" cy="50" r="50" mask="url(#myMask)" />
</svg>

注:这里的蒙版与PS中的蒙版极其相似,总结一个要领就是白透黑不透,不懂也没关系我们继续。

渐变 <linearGradient> / <radialGradient>

11.png

<svg width="200" height="100" viewBox="0 0 200 100">
    <defs>
      <!-- 线性渐变 -->
      <linearGradient id="myLinearGradient">
        <stop offset="0%"  stop-color="gold" />
        <stop offset="100%" stop-color="red" />
      </linearGradient>
      <!-- 径向渐变 -->
      <radialGradient id="myRadialGradient">
        <stop offset="0%" stop-color="gold" />
        <stop offset="100%" stop-color="red" />
      </radialGradient>
    </defs>
    <circle cx="50" cy="50" r="45" fill="url(#myLinearGradient)" />
    <circle cx="150" cy="50" r="45" fill="url(#myRadialGradient)" />
</svg>

滤镜 <filter>

12.png

<svg width="200" height="100" viewBox="0 0 200 100">
    <filter id="blurMe">
      <feGaussianBlur stdDeviation="5"/>
    </filter>
    <circle cx="50" cy="50" r="45" />
    <circle cx="150" cy="50" r="45" filter="url(#blurMe)" />
</svg>

动画 <animate>

13.gif

<svg width="200" height="200" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg">
    <rect x="10" y="10" width="100" height="100">
      <animate attributeName="rx" values="0;50;0" dur="10s"
               repeatCount="indefinite" />
    </rect>
</svg>

纹理 <pattern>

14.png

<svg width="200" height="100" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
    <defs>
      <pattern id="star" viewBox="0,0,10,10" width="10%" height="10%">
        <polygon points="0,0 2,5 0,10 5,8 10,10 8,5 10,0 5,2"/>
      </pattern>
    </defs>
  
    <circle cx="50"  cy="50" r="45" fill="url(#star)"/>
    <circle cx="150" cy="50" r="35" fill="none" stroke-width="20" stroke="url(#star)"/>
</svg>

复用 <use>

15.png

<svg width="200" height="100" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
    <circle id="myCircle" cx="30" cy="50" r="29" stroke="inherit" fill="inherit" />
    <use href="#myCircle" x="70" fill="black" stroke="red" />
    <use href="#myCircle" x="140" fill="transparent" stroke="black"/>
</svg>

好了,至此SVG中常用的标签已经看了个七七八八了,当然还有很多标签没有涉猎,不过,以上这些标签足以应付大部分需要SVG出马的场景了,至于剩下的那些只要现学现用就好。

接下来,请容许我隆重介绍一款SVG开发利器。

你是否经常想不起SVG的语法而去翻找曾经写过的代码?

你是否经常忘记SVG的渐变有哪些属性?

你是否经常分不清楚<path>ACSQT这些命令到底有啥区别?

上面讲的常用标签记不住?没关系!

刚才提到的语法命令不会用?没关系!

俗话说脑力不够,插件来凑,笨人有笨人的办法,于是乎,我为自己开发了一个小插件,功能很简单,只是进行一些代码补全,大佬肯定瞧不上眼的,自用是够了,容我演示一下它的功能。

它可以补全SVG中的常用标签:

43.gif

还可以补全常用的<defs>标签:

44.gif

还有<path>中的命令语法提示:

45.gif

当然,也有其他非SVG的语法补全,例如vue2.0vue3.0的模板,常用CSS(如缩略、渐变】、动画等)、也有JS中字符串和数组的常用方法,这些就不一一演示了,感兴趣的小伙伴可以去vscode商店搜索propeller,有插件文档,欢迎下载试用。

46.jpg

如果它真的能让你的开发效率提升那么一丢丢,我会特别特别开心,好了,下一篇,我们来讲讲 SVG擅长些啥?