svg入门

什么是SVG

SVG是一种XML语言,可以用来绘制矢量图形。SVG可以通过定义必要路径和形状来创建一个图形,也可以修改已有的位图,或者将这两种方式结合起来创建图形。

主流的浏览器均支持SVG。

优点:

  • 实现了DOM接口(比Canvas方便),方便添加事件
  • 可任意伸缩,SVG绘制的图形放大或缩小都不会失真

缺点:渲染慢。浏览器需要根据这些定义计算出在屏幕上渲染时应该呈现的样子。越复杂的SVG会在浏览器中占用很长的处理时间。

SVG提供了一些元素,用于定义圆形、矩形、椭圆、线等。
一个简单的SVG文档由 <svg> 元素和基本的形状元素构成。当然,SVG也可以变得很复杂,支持渐变、旋转、动画、滤镜效果、与JavaScript交互等等。

注意📢:SVG的元素和属性区分大小写,属性值必须用引号引起来。

坐标系统

SVG使用的坐标系统跟HTML文档一样:以页面的左上角为(0,0)坐标点,坐标以像素为单位,x轴正方向是向右,y轴正方向是向下。


image.png

基本形状

svg提供了6个基本形状,可以在 <svg> 中创建对应的元素来描述图形。
svg相当于一块布,图形的坐标都是相对于svg而言的。

矩形

矩形 rect 元素,必要的 4 个属性:

  • 左上角的坐标 (x,y)
  • 矩形的宽度 width 和高度 height

如下,在坐标 (0,0) 定义了一个宽高都是30 的矩形:

<svg width="200" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg">
        <rect x="0"  y="0"  width="30" height="30"/>
</svg>
image.png

除此之外,还有 rx 和 ry 两个属性用来控制矩形的角:

<svg width="200" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg">
        <rect x="0" y="0" rx="10" ry="10" width="30" height="30"/>
</svg>
image.png

圆形

circle 元素用来绘制圆形,只有3个必要属性:

  • r 半径
  • cx 和 cy (圆心坐标)
<svg width="200" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <circle cx="25" cy="75" r="20"/>
</svg>
image.png

椭圆

ellipse 元素可以创建椭圆,跟圆形的区别是,椭圆把半径拆成了 rx(x半径)和ry(y半径):

<svg width="200" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <ellipse cx="75" cy="75" rx="20" ry="15" />
</svg>
image.png

当 rx === ry 时,椭圆就变成了圆。

直线

line 用来描述直线,需要指定起点和终点。
分别是x1、 y1 和 x2 、y2。

<svg width="200" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <line x1="10" x2="50" y1="110" y2="150" stroke="red"/>
</svg>
image.png

折线

polyline用来描述折线。
所谓折线,是由许多连续的线段组成。
也就是说,它包含了很多的点,折线的所有点位置都放在points属性中,写法如下:

  • 每个数字用空格隔开,每个点用逗号分隔开。
  • 每个点必须包含2个数字,一个是x坐标,一个是y坐标。所以点列表 (0,0), (1,1) 和(2,2)可以写成这样:“0 0, 1 1, 2 2”。
<svg width="200" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <polyline points="60 110, 75 130, 80 180, 100 120" stroke="red" fill="transparent"/>
</svg>
image.png

多边形

polygon 用来描述多边形,它和折线很像,也是由连接一组点集的直线构成。不同的是,polygon的路径在最后一个点处会自动回到第一个点,也就是自动闭合。
下面代码只是 把 polyline 换成了 polygon:

<svg width="200" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <polygon points="60 110, 75 130, 80 180, 100 120" stroke="red" fill="transparent"/>
</svg>
image.png

路径

path 用来描述路径,它是所有 SVG 绘制工具中最强大的,也是最复杂的。

你可以用 path 元素绘制矩形(直角矩形或者圆角矩形)、圆形、椭圆、折线、多边形,以及一些其他的复杂形状(前提是你写得出来)。

d 属性表示绘制命令,它的值是一个长字符串。 每个字母表示一个绘制动作,后面跟着坐标:

  • M:移动到(move to)
  • L:画直线到(line to)
  • H:一条水平线,只接受x坐标
  • V:一条垂直线,只接受y坐标
  • Z:闭合路径
<svg width="200" height="500" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <path d=" M 18,3 L 46,3 V 40 H 61 L 32,68 L 3,40 H 18 Z"/>
</svg>
image.png

文本

text 元素用来添加文本。
属性 x 和属性 y 决定文本在视口中显示的位置。属性 text-anchor,可以有这些值:start、middle、end或inherit,允许决定从这一点开始的文本流的方向。

几个text-anchor值的对比如下:

<svg>
    <text x="0" y="10" >文本</text>
    <text x="0" y="50"  text-anchor="start">文本</text>
    <text x="0" y="90" text-anchor="middle">文本</text>
    <text x="0" y="140" text-anchor="end">文本</text>
</svg>
image.png

从上图可看出:

  • start是默认,表示从文本最左边开始显示。
  • middle表示从文本中间开始显示。
  • end表示从文本末尾开始显示 (没了)。

文本路径

如果要使得文本沿着某条路径排列,则需要使用textPath 元素。把文本放在 textPath 元素内部,然后使用 textPath 元素的 xlink:href 属性引用一个定义好的 path 元素。
在下面的例子,首先定义了一个路径 id 为 path,然后在 textPath 通过 xlink:href 指向该 id 作为文本的 path,最后通过 use 把 path 也画出来:

<svg width="500" height="500" >
    <defs>
        <path id="path"
          d="M10,50
             C10,50 50,0 100,50
             C100,50 150,100 190,50" />
    </defs>
   <g fill="blue" >
      <text x="20">
          <textPath xlink:href="#path">
               textPath
          </textPath>
      </text>
   </g>
   <use xlink:href="#path" fill="none" stroke="blue" />
</svg>
image.png

图片

SVG元素可以包含图像信息。

<svg width="100" height="100" viewBox="0 0 100 100"
     xmlns="http://www.w3.org/2000/svg">
    <image xlink:href="https://lf-cdn-tos.bytescm.com/obj/static/xitu_extension/static/brand.a9595735.svg" x="0" y="0" height="100" width="100" />
</svg>
image.png
  • xlink:href 图片地址。
  • x:图片左顶点x坐标。
  • y:图片左顶点y坐标。
  • width:图片宽度,必须。
  • height:图片高度,必须。

其他元素

g

g 元素用于将多个形状组成一个组,定义在g上的样式对所有子元素生效。

<svg width="300" height="100">
  <g id="circle" fill="red">
    <text x="25" y="20">圆形</text>
    <circle cx="50" cy="50" r="20"/>
  </g>
</svg>
image.png

use

use 用于复用已有的形状,通过设置 href 指定要复制节点的id。
x属性和y属性是use左顶点的坐标。

<svg width="300" height="100">
  <g id="circle">
    <text x="25" y="20">圆形</text>
    <circle cx="50" cy="50" r="20"/>
  </g>
  
  <use href="#circle" x="200" y="0"  />
  <use href="#circle" x="100" y="0" fill="red" />
</svg>
image.png

defs

defs 元素用于定义一个形状,也就是说内部代码不会在页面显示。定义的形状可供 use 元素引用,例如对上面的例子加上一层 defs:

<svg width="300" height="100">
  <defs>
    <g id="circle">
      <text x="25" y="20">圆形</text>
      <circle cx="50" cy="50" r="20"/>
    </g>
  </defs>
  
  <use href="#circle" x="200" y="0"  />
  <use href="#circle" x="100" y="0" fill="red" />
</svg>
image.png

animate

动画元素放在形状元素的内部,用来定义一个元素的某个属性如何踩着时点改变。在指定持续时间里,属性从开始值变成结束值。

  • attirbuteName:父元素的需要被改变的属性名。
  • from:单次动画的初始值。
  • to:单次动画的结束值。
  • dur:单次动画的持续时间,>0。
  • repeatCount:这个属性的值指定了重复的次数。值可以是:number | "indefinite"。
<svg width="500px" height="500px">
  <rect x="0" y="0" width="100" height="100" fill="#feac5e">
    <animate attributeName="width" from="0" to="100" dur="1s" repeatCount="indefinite" />
  </rect>
</svg>
drdde-hbozt.gif

样式属性

以下是常用的样式属性。

  • stroke:线条颜色
  • stroke-width:线条宽度
  • stroke-opacity:线条透明度
  • stroke-linecap:笔画头的形状 butt(默认), round, square
  • fill:填充色,设置形状内部的颜色
  • fill-opacity:填充透明度

渐变

渐变有两种,线性渐变和径向渐变。

线性渐变

svg使用 linearGradient 元素来定义线性渐变。
线性渐变需要预先定义,使用前需要先通过 defs 定义,然后在 linearGradient 元素上指定 id,使用时指定该 id:

<defs>
    <linearGradient id="linear"></linearGradient>
</defs>

接着,在<linearGradient>中创建<stop>元素,添加需要的颜色:

  • stop-color: 想要设定的渐变颜色
  • offset: 在你定义的方向向量上,定义该颜色的生效位置,使用百分比来设置具体的存在位置。
  • stop-opacity: 设定stop-color颜色的透明度
<defs>
    <linearGradient id="linear">
        <stop stop-color="#a0b3d6" offset="0%" />
        <stop stop-color="red" offset="100%" />
    </linearGradient>
</defs>

然后在样式里面通过 id 引入该渐变:

<rect x="0" y="0"  width="30" height="30" fill="url(#linear)"/>
image.png

径向渐变

<radialGradient>有点像是线性渐变和<circle>元素属性的混合。同样需要先创建一个<defs>声明,然后将<radialGradient>添加在其中,并为其赋予唯一的id值以方便后面的填充引用。

<svg width="500" height="400">
    <defs>
        <radialGradient r="50%" cx="50%" cy="50%" id="radial">
            <stop stop-color="#a0b3d6" offset="0%" />
            <stop stop-color="red" offset="100%" />
        </radialGradient>
    </defs>
    <rect x="0" y="0"  width="50" height="50" fill="url(#radial)"/>
    <circle cx="100"  cy="30" r="30" fill="url(#radial)"/>
</svg>
  • cx、cy属性设定圆心点(默认50%)
  • 渐变范围则通过属性r设定(默认50%)


    image.png

变形

平移

类似 CSS 的平移,translate() 用于SVG的平移操作。

<svg width="500" height="500">
    <rect x="0" y="0" width="10" height="10" transform="translate(100,100)" />
</svg>

在上面的例子里面,矩形的左顶点是(0,0),通过平移后,移到了(100,100)。


image.png

旋转

类似CSS的平移,rotate()用于SVG的旋转操作。
旋转默认是以svg的左顶点为中心旋转的。
在下面例子中,把 rect 绕着 svg 左顶点旋转45°:

<svg width="500" height="400">
         <rect x="30" y="30" width="120" height="90" fill="red"/>
         <rect x="30" y="30" width="120" height="90" fill="#a0b3d6" transform="rotate(45)"/>
</svg>

红色矩形是没有旋转的情况,蓝色矩形旋转45°:


image.png

多数情况下,我们想要的是绕着中心点旋转。rotate(c[, x, y]) 可以加上要旋转的中心坐标,例如上面的例子,x = 30 + 120/2 = 90,y = 30 + 90/2 = 75:

<svg width="500" height="400">
         <rect x="30" y="30" width="120" height="90" fill="red"/>
         <rect x="30" y="30" width="120" height="90" fill="#a0b3d6" transform="rotate(45, 90, 75)"/>
</svg>
image.png

缩放

scale() 变形改变了元素的尺寸。

<svg width="500" height="500">
    <rect x="20" y="20" width="20" height="20" transform="scale(1,2)" />
</svg>

通过scale(1,2),把一个正方形变成长方形


image.png

斜切

skewX()和skewY(),每个需要一角度以确定元素斜切到多远。

<svg width="500" height="500">
    <rect x="20" y="20" width="20" height="20" transform="skewX(45)" />
</svg>
image.png

总结

本篇文件从svg的语法以及基本的使用介绍了svg的元素。当然了,在实际开发中,运用svg一般是从UI给出的设计稿中直接导出svg使用的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • 一、栅格图形和矢量图形栅格图形:也称位图,图像由一组二维像素网格表示。Canvas 2d API 就是一款栅格图形...
    linda102阅读 1,136评论 0 4
  • 本文简介 点赞 + 关注 + 收藏 = 学会了 作为一只前端,只懂 Vue、React 感觉已经和大家拉不开距离了...
    德育处主任阅读 1,284评论 0 18
  • 概念 SVG全称是可缩放矢量图(Scalable Vector Graphics),是一种基于XML语法,用于描述...
    belllee阅读 1,043评论 0 0
  • <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLI...
    穆熙沐阅读 399评论 0 1
  • 1.svg文件引入 可通过 , 引入使用 理论上同样可以使用 img 元素,但是在低于4.0版本的Firefox...
    Jmingzi_阅读 329评论 0 0