SVG 入门学习笔记 (1W字)

最近因为公司业务需要,需要做大屏可视化组件,技术库D3.js,翻阅D3.js官方文档,也是基于SVG的,那就从SVG开始入坑吧!!

ps:感觉可视化的东西都好麻烦好麻烦

无聊的概念

图形系统

我们的计算机有两种图形系统: 栅格图形 矢量图形

  • 栅格图形系统就是那种越放大越模糊的图片。
  • 矢量图形就是怎么放大都好清晰的辣种。 (比如这个炸鸡emoji)。用官方的回答翻译过来就是: 矢量图形中图形被描述为一系列几何形状,通过矢量图形阅读器在指定的坐标集上绘制形状。

SVG(Scalable Vector Graphics)可拓展矢量图形

看这名字又能 拓展 又是 矢量 ,很高端有没有 。

矢量是什么,上面提到啦,怎么放大都很清晰。

SVG是一种XML应用(XML啊,就是跟HTML差的多 的一种 标记语言 ),用来表示矢量图形。

SVG所有的图形有关信息被存储为 纯文本 ,因为SVG也是XML的一种应用嘛,所以理应继承XML的开放性、可移植性和可交互性。

所以到此我们应该懂啦,SVG就是定义了一些图形信息,比如坐标啥的,然后浏览器会根据这些坐标去进行绘制。

举个栗子 :像emoji这种,有时候有没有发现,你在输入法点的emoji跟显示的不一样,其实它发的就是一段编号,然后浏览器在字体里面找,但是每个电脑装的字体不一定一样,所以就显示出来有差异啦。

所以SVG保存的也是定义的信息,并不是用图像进行传输。

开始使用SVG

如果此时设计师给了一个SVG图片,怎么使用嘞~~

将SVG作为图像

<img src="./404.svg" alt="404" />

将svg作为图像包含在HTML标记的img元素内,但是这样有一定的局限性:SVG转为栅格图像时与主页面分离(也就是会分开渲染 ),并且无法在两者之间通信(SVG渲染过程与主页面独立)。

主页面上的样式对SVG无效,运行在主页面上的脚本无法感知或者修改SVG文档结构。

将SVG作为应用程序

<html>
 <object type="image/svg+xml" data="MySVG.svg"
    width="300" height="200">
 </object>
</body>
</html>

使用object元素将SVG嵌入HTML文档中,object元素的type属性表示要嵌入的文档类型,对用SVG应该是type="image/svg+xml"。object元素必须有起始标签和结束标签,这两个标签之间的内容为对象数据本身不能被渲染时显示。

感觉这种用不上啊有没有

或者直接把svg放到html里也行

<html>
 </svg>
</body>
</html>

坐标系统

视口

视口代表文档想使用的区域,用width和height确当视口大小,单位可以仅仅是数字也可以是带单位的数字

<html>
    <svg width="200" height="100">
    </svg>
</body>
</html>



默认用户坐标

SVG会设置坐标系统,原点(0,0)位于视口的左上角,x从左向右依次递增,y从上到小依次递增。

SVG的元素的单位可以不统一。(看下面的示例代码 )

<svg width="600" height="300" style="outline: 5px solid #e6e6e6">  
        //x y 设定位置
        <rect x="10px" y="10px" width="10" height="10" fill="blue" />  
        <rect x="4em" y="1em" width="10" height="10" fill="pink" />
        <rect x="10" y="50" width="10" height="10" fill="yellow" />
</svg>



指定用户坐标

可以自己为视口设置坐标系,通过SVG元素上的viewBox属性。viewBox分别代表叠加再坐标系上的四个属性

viewBox( minX, minY, width, height)

那么如何使用嘞,举个栗子 :

比如定义了一个圆形,

<svg width="300" height="300" style="outline: 5px solid #e6e6e6">  
        <circle cx="200" cy="200" r="200" fill="#fdd" stroke="none"></circle>
</svg>



如果是在一个400*400的画布上,圆正好撑满整个画布,挺好的。

好了,然后我要把这个圆嵌入到自己的页面里的svg标签里去,页面的svg标签尺寸是由实际业务需要来定的,不一定正好是,可能大可能小,还可能不是正方形。(比如上图是300*300的正方形)

可以看到圆形都没显示完全,这该怎么办呢

svg尺寸不能更改,那就到了viewBox的用武之地了 嘿嘿

<svg width="300" height="300" viewBox="0 0 400 400" style="outline: 5px solid #e6e6e6">  
        <circle cx="200" cy="200" r="200" fill="#fdd" stroke="none"></circle>
    </svg>



圆变小了,展示全了,还垂直居中了。 nice

viewBox的四个参数分别代表:最小X轴数值;最小y轴数值;宽度;高度。

前两个暂时用不到,个人理解除非要对内部svg做整体位移,否则一般都是0 0,暂时先不做解释,重点关注后两个参数。

想象一下viewBox是个400*400的正方形,但是单位不是px,也不是任何一个css单位,就当是一个假的单位吧。在viewBox放了一个圆,这个圆的半径是200,单位也不是px,而是变成了和viewBox的单位一模一样的那个假的单位。为啥说是假的呢?因为这个单位代表的长度是会变的,接着看。

svg有个特点,在默认情况下,会调整这个viewBox的大小,让这个viewBox正好能被放进svg里去。拿上面例子来说,viewBox是个正方形,而svg的宽度比高度小,所以就把viewBox的大小缩小到和svg宽度一样,就能正好将viewBox放进svg里来了。所以现在viewBox的实际大小是个150px*150px的正方形。

所以现在可以确定的是,viewBox的一个单位代表的长度 = 150px/400 = 0.375px。 而viewBox内部的所有数值*0.375px才是真正的长度。那个circle的圆心实际上是在坐标75px, 75px的位置上,半径为75px。

圆的具体大小大概就是这么回事。

为了解决SVG视口长宽比例和viewBox定义的长宽比例不同的问题以及如何对齐问题。这个时候就需要preserveAspectRatio属性了。

如果viewBox的比例与视口比例不同,则有三种可能:

  • a. 按较小的尺寸等比例缩放图形,使图形完全填充视口
  • b. 按较大的尺寸等比例缩放图形,病裁减掉超出视口的部分
  • c. 拉伸和压缩绘图以使其恰好填充视口

PreserveAspectRadio 属性

英文直译:维持外观比例。好像还挺语义化 的一属性名。

preserveAspectRatio属性允许指定被缩放的图形相对视口的对齐方式,格式为preserveAspectRatio = "alignment[meet|slice]"

默认值为"xMidYMid meet"

<svg style="width:150px; height:300px" viewBox="0 0 400 400" preserveAspectRatio="xMidYMid meet">

meet 说明符在图形超出视口时候会对图形适当缩小调整适配可用的空间

slice 说明符直接裁剪超出视口的部分

总共有9个值可选:

| ||| |----|----|----| | xMinYMin| xMinYMid | xMinYMax| |xMidYMin |xMidYMid|xMidYMax| |xMaxYMin|xMaxYMid|xMaxYMax|

x和y表示对齐的轴线,min,mid,max表示对齐的方式。min是往坐标小的方向对齐;mid居中对齐;max是往坐标大的方向对齐(顺带一提svg的坐标0刻度在左上角)。

第二个参数有两个值可选:meet和slice meet就是前面那种自动调整viewBox到可以在svg画布中完全展示。非常类似css里background-size:contain 而slice是自动调整viewBox到撑满整个svg画布。非常类似background-size:cover

再回看第二张图里那个垂直居中的圆,就能明白为什么会“圆变小了,展示全了,还垂直居中了”。

还可以指定preserveAspectRatio="none",用于在viewBox和视口宽高比不同时缩放图像,此时图像不会被等比例缩放,会被拉伸、挤压、变形。

参考文章链接

链接: segmentfault.com/a/1190

基本形状

线段

line元素,使用x1,y1,x2,y2属性指定线段的起止点坐标。

<svg width="300" height="300" style="outline: 5px solid #e6e6e6">  
        <line x1="50" y1="50" x2="300" y2="300" stroke="crimson" stroke-width="2" />
</svg>



  • stroke定义笔画颜色
  • stroke-width定义笔画宽度

当然你也可以把以上两个属性写到style里

矩形

rect元素,使用x,y,width,height表示一个矩形

<svg width="300" height="300" style="outline: 5px solid #e6e6e6">  
       <rect x="50" y="50" width="100" height="50"></rect>
</svg>



圆和椭圆

circle元素表示圆,由cx,cy,r属性界定 ellipse元素表示椭圆,由cx,cy,rx,ry界定

<svg width="300" height="300" style="outline: 5px solid #e6e6e6">  
        <circle cx="100" cy="100" r="50"></circle>
    <svg width="300" height="300" style="outline: 5px solid #e6e6e6">  
        <ellipse cx="100" cy="100" rx="50" ry="60"></ellipse>
    </svg>



多边形

polygon元素指定一个多边形,由points属性指定的一系列坐标点界定,会自动封闭

<svg width="300" height="300" style="outline: 5px solid #e6e6e6">  
        <polygon points=" 50,50 100,100 30,60" stroke="crimson" stroke-width="2"></polygon>
</svg>



折线

polyline元素表示一个折线,使用points属性指定一系列点,不自动封闭图形。 注意下图红线没有封闭哦

<svg width="300" height="300" style="outline: 5px solid #e6e6e6">  
        <polyline points=" 50,50 100,100 30,60" stroke="crimson" stroke-width="2"></polyline>
</svg>



特性总结

| 特性 | 说明 | | ---- | ---- | | stroke| 笔画颜色| |stroke-width| 笔画宽度| |stroke-opacity| 笔画不透明度| |stroke-dasharray| 虚线笔画| |stroke-linecap| 笔画头的形状 butt(默认),round,square| |stroke-linejoin| 图形棱角,有miter(默认),round和bevel三个取值| |stroke-miterlimit| 相交处显示宽度与线宽的最大比例,默认为4| |fill |填充颜色 默认black| |fill-opacity|填充不透明度| |fill-rule| 填充规则|

是不是感觉还挺简单哒,继续

文档结构

结构与表现

SVG允许文档表现和文档结构分离(就是跟CSS一样,能写成单独的文件 ),SVG支持四种方式指定表现信息:内联样式、内部样式表、外部样式表(跟CSS一毛一样 )以及表现属性。

  • 表现属性 SVG允许以属性的形式指定表现样式,但是表现属性的优先级最低,如果以其他三种形式指定了相同的样式属性,则将覆盖通过表现属性指定的样式

分组和引用

g元素用来将其子元素作为一个组合,可以使文档结构更清晰。除此之外,在g标签中指定的所有样式会应用于组合内的所有子元素,可以不用在所有子元素上指定属性。

举个栗子 :



如上图的鸟的每一部分都是由一个个图形组合而成,而在软件中当需要整体移动时,则需要



在svg中同理,如下代码将bird分为一个大组

<svg width="1144.12px" height="400px" viewBox="0 0 572.06 200">
    <style>
        svg{background-color:white;}
        #wing{fill:#81CCAA;}
        #body{fill:#B8E4C2;}
        #pupil{fill:#1F2600;}
        #beak{fill:#F69C0D;}
        .eye-ball{fill:#F6FDC4;}
    </style>
    <g id="bird">
        <g id="body">
            <path d="M48.42,78.11c0-17.45,14.14-31.58,31.59-31.58s31.59,14.14,31.59,31.58c0,17.44-14.14,31.59-31.59,31.59
            S48.42,95.56,48.42,78.11"/>
            <path d="M109.19,69.88c0,0-8.5-27.33-42.51-18.53c-34.02,8.81-20.65,91.11,45.25,84.73
            c40.39-3.65,48.59-24.6,48.59-24.6S124.68,106.02,109.19,69.88"/>
            <path id="wing" d="M105.78,75.09c4.56,0,8.84,1.13,12.62,3.11c0,0,0.01-0.01,0.01-0.01l36.23,12.38c0,0-13.78,30.81-41.96,38.09
            c-1.51,0.39-2.82,0.59-3.99,0.62c-0.96,0.1-1.92,0.16-2.9,0.16c-15.01,0-27.17-12.17-27.17-27.17
            C78.61,87.26,90.78,75.09,105.78,75.09"/>
        <g id="head">
            <path id="beak" d="M50.43,68.52c0,0-8.81,2.58-10.93,4.86l9.12,9.87C48.61,83.24,48.76,74.28,50.43,68.52"/>
            <path class="eye-ball" d="M60.53,71.68c0-6.33,5.13-11.46,11.46-11.46c6.33,0,11.46,5.13,11.46,11.46c0,6.33-5.13,11.46-11.46,11.46
                C65.66,83.14,60.53,78.01,60.53,71.68"/>
            <path id="pupil" d="M64.45,71.68c0-4.16,3.38-7.53,7.54-7.53c4.16,0,7.53,3.37,7.53,7.53c0,4.16-3.37,7.53-7.53,7.53
                C67.82,79.22,64.45,75.84,64.45,71.68"/>
            <path class="eye-ball" d="M72.39,74.39c0-2.73,2.22-4.95,4.95-4.95c2.73,0,4.95,2.21,4.95,4.95c0,2.74-2.22,4.95-4.95,4.95
                C74.6,79.34,72.39,77.13,72.39,74.39"/>
</svg>

use元素用来复用图形中重复出现的元素,需要为use标签的xlink:href指定URI来引用指定的图形元素。同时还要指定x和y属性以表示组合应该移动到哪个位置。use元素并不限制只能使用同一个文件内的对象,xlink:href属性可以指定任何有效的文件或URI。

举个栗子 :

<svg width="1144.12px" height="400px" viewBox="0 0 572.06 200">
    <style>
    </style>
    <g id="bird">
    <!--在这使用use-->
    <use x="130" y="50" xlink:href="#bird" />
</svg>



引用链接

blog.csdn.net/a46055054

坐标系统变换

translate变换

translate用来对坐标进行平移,通过制定transform属性值来设置transform=transform(x,y)

<svg width="1144.12px" height="400px" viewBox="0 0 572.06 200" style="outline: 5px solid #e6e6e6">
    <style>
        svg{background-color:white;}
        #wing{fill:#81CCAA;}
        #body{fill:#B8E4C2;}
        #pupil{fill:#1F2600;}
        #beak{fill:#F69C0D;}
        .eye-ball{fill:#F6FDC4;}
    </style>
    <g id="bird">
        <g id="body">
            <path d="M48.42,78.11c0-17.45,14.14-31.58,31.59-31.58s31.59,14.14,31.59,31.58c0,17.44-14.14,31.59-31.59,31.59
            S48.42,95.56,48.42,78.11"/>
            <path d="M109.19,69.88c0,0-8.5-27.33-42.51-18.53c-34.02,8.81-20.65,91.11,45.25,84.73
            c40.39-3.65,48.59-24.6,48.59-24.6S124.68,106.02,109.19,69.88"/>
            <path id="wing" d="M105.78,75.09c4.56,0,8.84,1.13,12.62,3.11c0,0,0.01-0.01,0.01-0.01l36.23,12.38c0,0-13.78,30.81-41.96,38.09
            c-1.51,0.39-2.82,0.59-3.99,0.62c-0.96,0.1-1.92,0.16-2.9,0.16c-15.01,0-27.17-12.17-27.17-27.17
            C78.61,87.26,90.78,75.09,105.78,75.09"/>
        <g id="head">
            <path id="beak" d="M50.43,68.52c0,0-8.81,2.58-10.93,4.86l9.12,9.87C48.61,83.24,48.76,74.28,50.43,68.52"/>
            <path class="eye-ball" d="M60.53,71.68c0-6.33,5.13-11.46,11.46-11.46c6.33,0,11.46,5.13,11.46,11.46c0,6.33-5.13,11.46-11.46,11.46
                C65.66,83.14,60.53,78.01,60.53,71.68"/>
            <path id="pupil" d="M64.45,71.68c0-4.16,3.38-7.53,7.54-7.53c4.16,0,7.53,3.37,7.53,7.53c0,4.16-3.37,7.53-7.53,7.53
                C67.82,79.22,64.45,75.84,64.45,71.68"/>
            <path class="eye-ball" d="M72.39,74.39c0-2.73,2.22-4.95,4.95-4.95c2.73,0,4.95,2.21,4.95,4.95c0,2.74-2.22,4.95-4.95,4.95
                C74.6,79.34,72.39,77.13,72.39,74.39"/>
    <!--我们在use上使用tranform-->
    <use x="1" y="50" xlink:href="#bird" transform="translate(0,0)" />
</svg>

在use上使用translate(0,0),将图像移动到了原图像的中心点上。ps:这说明移动的点基于原图像的中心哒



  • 工作原理:首先获取整个表格,然后将其移动到画布的新位置,而不是移动到所在的元素,所以说 移动的是坐标系 而不是元素本身。

scale变换

缩放坐标系统,transform = "scale(value)"或者transform="scale(x-value,y-value)"。

使用scale(n)变换时,网格系统的原点没有改变,只是用户坐标变成了原来的n倍,也就是网格变大了,因此线也会变粗。

<use x="1" y="50" xlink:href="#bird" transform="scale(0.5)" />



可以看到小鸟变小啦

缩放变换永远不会改变图形对象的网格坐标或者笔画宽度,仅仅改变对应画布上的坐标系统网格的大小。

rotate变换

根据指定的角度旋转坐标系统,默认的坐标系统中,角度的测量顺时针增加,0度为3点钟方向。

<use x="1" y="50" xlink:href="#bird" transform="rotate(30,100,100)" />



可以看到小鸟转了30度 哈哈哈

注意 ,除非另行指定,否则旋转以原点为中心。 此时可以通过平移+旋转的方式来指定旋转中心: translate(centerX,centerY) rotate(angle) translate(-centerX,-centerY)

但是有个更简单的方式:rotate(angle,centerX,centerY)

skewX和skewY变换

这两个变换用来倾斜某个轴,一般形式为skewX(angle),skewY(angle)。这样的结果就是使得x轴和y轴不再垂直。



<use x="1" y="50" xlink:href="#bird" transform="skewX(30)" />

矩阵变换

计算机图形学中坐标变换都通过矩阵来实现,除上述变换方法之外,还可以直接为变换指定变换矩阵,变换矩阵为matrix(a,b,c,d,e,f),此时指定的变换矩阵为:

a  c  e
b  d  f
0  0  1



<use x="1" y="50" xlink:href="#bird" transform="matrix(2,1,1,0,1,1)" />

矩阵转换依据,参考线性代数哦

路径

Path命令

SVG中所有基本形状都是path的简写形式,但是建议使用简写形式,因为这样可以使SVG文档更可读

path元素更通用,可以通过制定一系列相互连接的线、弧、曲线来绘制任意形状的轮廓,这些轮廓也可以填充或者绘制轮廓线,也可以用来定义裁剪区域或蒙版。

举个例子 :



<svg width="1144.12px" height="400px" viewBox="0 0 572.06 200" style="outline: 5px solid #e6e6e6">
    <path d="M150 0 L75 200 L225 200 Z" />
</svg>

参考下面的表,可以看到,它开始于位置150 0,到达位置75 200,然后从那里开始到225 200,最后在150 0关闭路径。 Z = closepath,下面没写

ps:这就可以解释为啥SVG是矢量的了

下表为path命令总结,其中大写表示绝对坐标,小写表示相对坐标:

| 命令 | 参数| 说明| | ---- | ---- | ---- | |M m |x y |移动画笔到制定坐标| |L l| x y| 绘制一条到给定坐标的线| |H h| x |绘制一条到给定x坐标的横线| |V v| y |绘制一条到给定y坐标的垂线| |A a| rx ry x-axis-rotation large-arc sweep x y| 圆弧曲线命令有7个参数,依次表示x方向半径、y方向半径、旋转角度、大圆标识、顺逆时针标识、目标点x、目标点y。大圆标识和顺逆时针以0和1表示。0表示小圆、逆时针| |Q q |x1 y1 x y |绘制一条从当前点到x,y控制点为x1,y1的二次贝塞尔曲线| |T t |x y |绘制一条从当前点到x,y的光滑二次贝塞尔曲线,控制点为前一个Q命令的控制点的中心对称点,如果没有前一条则已当前点为控制点。| |C c| x1 y1 x2 y2 x y| 绘制一条从当前点到x,y控制点为x1,y1 x2,y2的三次贝塞尔曲线 |S s| x2 y2 x y| 绘制一条从当前点到x,y的光滑三次贝塞尔曲线。第一个控制点为前一个C命令的第二个控制点的中心对称点,如果没有前一条曲线,则第一个控制点为当前的点。|

maker元素

marker元素用来在path上添加一个标记,比如箭头之类的。

举个栗子 :

SVG 中并没有箭头,可以通过进行扩展。

先定义一个箭头 defs理解的话就很定义一个函数一样

<defs>
            <marker id="markerArrow" markerWidth="13" markerHeight="13" refx="2" refy="6" orient="auto">
                <path d="M2,2 L2,11 L10,6 L2,2" style="fill: #000000;" />
            </marker>
</defs>

其中orient="auto"设置箭头的方向为自动适应线条的方向。

而后,画line ,line的marker-end引用上面定义好的markerArrow即可

<svg width="300" height="300" style="outline: 5px solid #e6e6e6">  
            <marker id="markerArrow" markerWidth="13" markerHeight="13" refx="2" refy="6" orient="auto">
                <path d="M2,2 L2,11 L10,6 L2,2" style="fill: #000000;" />
            </marker>
        </defs>
        <line x1="0" y1="0" x2="100" y2="50"  stroke="red" stroke-width="1" marker-end="url(#markerArrow)"  />
    </svg>



首先需要定义好marker元素,然后在path中引用,一个marker标记是一个独立的图形,有自己的私有坐标。

⛳图案和渐变

填充图形或笔画除了使用fill,stroke纯色之外,还可以使用图案和渐变填充。

图案

使用图案填充图形,首先要定义一个水平或垂直方向的重复的图案对象,然后用它填充另一个对象或者作为笔画使用。这个图形对象呗称为"tile"(瓷砖)。

举个栗子 :

<svg width="1000" height="1000" xmlns ="http://www.w3.org/2000/svg">
    <!--先定义一个图案-->
        <pattern id="strip" patternUnits="userSpaceOnUse" x="0" y="0" width="6" height="6">
            <path d="M0 0 6 0" style="stroke: black;fill: none"/>
        </pattern>
        <pattern id="polkadot" patternUnits="userSpaceOnUse" x="0" y="0" width="36" height="36" >
            <circle cx="12" cy="12" r="12" style="fill: url(#strip);stroke: black"/>
        </pattern>
    </defs>
    <!--使用-->
    <rect x="36" y="36" width="100" height="100" style="fill: url(#polkadot);fill:url(#polkadot);stroke: black"/>
</svg>



图案对象使用pattern元素定义,pattern元素内部包裹了图案的path元素。定义好之后下一个需要解决的问题是如何排列图案,那就需要使用patternUnits属性.

patternUnits = objectBoundingBox

如果希望图案的大小基于要填充对象的大小计算,则需要设置patternUnits属性为objectBoundingBox(0到1之间的小数或百分比),并需要指定图案左上角的x和y坐标。

patternUnits = userSpaceOnUse

除了基于被填充对象尺寸方式之外,还可以按用户单位制定图案的width和height。此时要设置patternUnits值为userSpaceOnUse。

patternContentUnits属性

在上面两个例子中,pattern元素内的path元素的坐标都是用户坐标,如果想基于被填充图形设置,则需要设置patternContentUnits属性。patternContentUnits属性默认为userSpaceOnUse,当设置patternContentUnits属性为objectBoundingBox时就可以使用百分比来设置图案的大小。 基本看上面辣个栗子就懂啦 。

线性渐变

线性渐变是一系列颜色沿着一条直线过渡,在特定的位置指定想要的颜色,被称为渐变点。渐变点是渐变结构的一部分,颜色是表现的一部分。

线性渐变使用linearGradient元素表示:

<defs>
    <linearGradient id="linear">
        <stop offset="0%" style="stop-color:#ffcc00;"></stop>
        <stop offset="100%" style="stop-color:#0099cc;"></stop>
    </linearGradient>
</defs>
    <rect x="20" y="20" width="200" height="100" style="fill:url(#linear);stroke:black;">
    </rect>



径向渐变

径向渐变的每个渐变点是一个圆形路径,从中心点向外扩散。设置方式与线性渐变大致相同。如果填充对象边界框不是正方形的,则过渡路径会变成椭圆来匹配边界框的长宽比。

<defs>
    <radialGradient id="radial" cx="50%" cy="50%" >
        <stop offset="0%" style="stop-color:#f00;"></stop>
        <stop offset="50%" style="stop-color:#0f0;"></stop>
        <stop offset="100%" style="stop-color:#00f;"></stop>
    </radialGradient>
</defs>
<rect x="20" y="20" width="200" height="200" style="fill:url(#radial);stroke:black;"></rect>



文本

相关术语

看一眼就好,跟CSS属性差不多

|术语| 说明| | ---- | ---- | |字符| XML中,字符是指带有一个数字值得一个或多个字节,数字值与Unidode标准对应| |符号| 字符的视觉呈现。每个字符可以有多种视觉呈现| |字体| 代表某个字符集合的一组符号| |基线| 字体中所有符号以基线对齐| |上坡度| 基线到字体中最高字符的顶部距离| |下坡度| 基线到最深字符底部的距离| |大写字母高度、x高度| 大写字母高度是指基线上大写字母的高度,x高度是基线到小写字母x顶部的高度|

text元素的基本属性

text元素以指定的x和y值作为元素内容第一个字符的基线位置,默认样式黑色填充、没有轮廓。

与css的text属性类似

<svg width="1000" height="1000">
 <text x="0" y="15" fill="red">I am Leon</text>
</svg>



tspan元素

text元素无法对文本进行换行操作,如果需要分行显示文本,则需要使用tspan元素。tspan元素与html的span元素类似,可以嵌套在文本内容中,并可以单独改变其内部文本内容的样式。

<text x="10" y="20" style="fill:red;">Several lines:
        <tspan x="10" y="45">First line</tspan>
        <tspan x="10" y="70">Second line</tspan>
</text>



tspan元素除大小,颜色等表现样式之外,还可以设置以下属性:

|属性 | 说明| |----|----| |dx,dy| x和y方向的偏移| |x,y| 对tspan进行绝对定位| |rotate| 旋转字符,可以同时设置多个值,这些值会依次作用在tspan包裹的字母上| |baseline-shift| 与dy属性设置上下标相比,这个属性更方便,当为super时,会上标。sub时为下标。仅仅在所在的tspan内有效|

纵向文本

文本一般从左到右排列,如果需要上下排列,则需要使用writing-mode属性。

设置writing-mode属性值为tb(top to bottom),可以将文本上下排列。



<svg width="1000" height="1000" xmlns ="http://www.w3.org/2000/svg">
    <text x="10" y="20" style="fill:red;writing-mode:tb">I am Leon</text>
</svg>

文本路径

如果要使得文本沿着某条路径排列,则需要使用textPath元素。需要将文本放在textPath元素内部,然后使用textPath元素的xlink:href属性引用一个定义好的path元素。

举个栗子 :

<svg width="1000" height="1000" >
        <path id="circlePath"
          d="M10,50
             C10,50 50,0 100,50
             C100,50 150,100 190,50
             M10,150
             C10,150 50,100 100,150
             C100,150 150,200 190,150" />
  </defs>
  <g fill="dodgerblue" font-size="15" font-family="楷体">
      <text x="20" y="40">
          <textPath xlink:href="#circlePath">
              SVG与文本:使用textPath进行字符串的显示
          </textPath>
      </text>
  <use xlink:href="#circlePath" fill="none" stroke="blue" />
</svg>



裁剪和蒙版

裁剪路径

clip-path属性可以防止部分元素通过定义的剪切区域来显示,仅通过显示的特殊区域。

我的天,这又是个啥

通俗的来说,就是在纸上面剪了个洞,然后你能看到的就是洞的区域。

举个栗子 :

我们先来绘制一个圆:



<svg width="200" height="200" style="outline: 5px solid #e6e6e6">
    <circle cx="60" cy="60" r="50" fill="#34538b" />
</svg>

再定义一个正方形让其成为裁剪路径

<svg width="200" height="200" style="outline: 5px solid #e6e6e6">
    <defs><!-- 定义 -->
        <clipPath id="clipPath"><!-- 定义剪裁路径 -->
            <rect x="0" y="0" width="80" height="80" /><!-- 路径详细 -->
        </clipPath>
    </defs>
    <circle cx="60" cy="60" r="50" fill="#34538b" clip-path="url(#clipPath)" />
</svg>



如图所示,被裁剪成了银杏叶 牛逼

在创建SVG文档时,可以通过指定感兴趣的区域的宽度和高度建立视口,这个视口就会变成默认的裁剪区域,裁剪区域外的任何部分都不会被显示。裁剪区域可以通过clipPath元素建立自己的裁剪区域。

参考链接

mybj123.com/4544.html

蒙版

SVG的蒙版会变换对象的透明度,如果蒙版是不透明的,则被蒙版覆盖的对象的像素就是不透明的,如果蒙版是半透明的,则对象就是半透明的。

举个栗子 :

黑色代表不可见(opacity: 0),白色代表可见(opacity: 100%)。

<svg> <defs> <linearGradient id='white2black'> <stop offset="0" stop-color="white"></stop> <stop offset="100%" stop-color="black"></stop> </linearGradient> <mask id="small-rect"> <rect x="0" y="0" width="400" height="300" fill="url(#white2black)"></rect> </mask> </defs> <rect id="back" x="0" y="0" width="400" height="300" fill="#d4fcff"></rect> <rect id="front" x="0" y="0" width="400" height="300" fill="#fcd3db" mask="url(#small-rect)"></rect> </svg>



参考链接

这里讲的更细

参考链接: segmentfault.com/a/1190

滤镜

工作原理

SVG阅读器处理一个图形对象时,会将对象呈现在位图输出设备上,它可以将对象的描述信息转化为一组对应的像素。在使用滤镜时,SVG阅读器不会直接将图形渲染为最终结果,而是先将像素保存到临时位图中,然后将滤镜指定的操作应用到该临时位图,其结果作为最终图形。

在SVG中,使用filter元素指定一组操作(也叫基元),在渲染图形对象时,将该操作应用在最终图形上。

filter标记之间就是我们想要的滤镜基元,每个基元有一个或多个输入,但是只有一个输出,输入可以是原始图形(SourceGraphic)、图形的阿尔法通道(不透明度,SourceAlpha)或者是前一个滤镜基元的输出。

创建投影效果

filter元素有一些属性用来描述该滤镜的裁剪区域。通过x,y,width,height属性定义一个滤镜范围,这些属性默认情况是按照对象的边界框计算的,即filterUnits属性的默认值为objectBoundingBox,如果要按照用户单位制定边界,则需要设置该属性值为userSpaceOnUse。

发光滤镜

feColorMatrix元素用来以一种通用的方式改变颜色值,可以用来创建一个发光的区域。

feImage滤镜

SVG的feImage滤镜允许使用任意的JPG\PNG\SVG文件或带有id属性SVG元素作为输入源。

光照效果

可以通过滤镜为图形添加光照效果,添加光照效果必须指定以下信息:

  • 反射类型:漫反射(feDiffuseLighting)或镜面反射(feSpecularLighting)
  • 想要照亮的对象
  • 使用的灯光颜色
  • 想要的光源类型:点光源(fePointLight),远光(FeFistantLight)或聚光灯(feSpotLight)

访问背景

除了SourceGraphic和SourceAlpha作为滤镜输入之外,还可以访问以及渲染到画布上的图片的某一部分,这部分内容称为backgroundImage和backgroundAlpha。为了访问这些输入信息,滤镜对象必须位于enable-background属性值为new的容器元素之内。

SVG动画

动画基础

SVG动画特性基于"同步多媒体集成语言"(SMIL)规范。在这个动画系统中,可以指定想要进行的动画的属性(颜色、动作或者变形等)的起始值和初始值,以及动画开始的时间和持续时间。

<rect x="10" y="10" width="200" height="200" stroke="black" fill="none">
    <animate 
        attributeName="width" 
        attributeType="XML" 
        from="200" to="20" 
        begin="0s" dur="5s" 
        fill="freeze">
    </animate>
</rect>

上述示例中,rect的宽度从200变化到20,历时5秒。rect不再是一个空元素,包含了动画元素animate。 如果需要在一个元素上指定多个属性的过渡则需要同时使用多个animate元素,分别指定过渡的这些元素的过渡属性。

animate元素指定了以下信息:

|属性| 说明| |----|----| |attributeName| 动画中改变的值| |attributeType| width是一个XML属性,另一个常用的值是CSS,如果忽略这个值,则默认是auto,会先搜索CSS属性,再搜索XML属性| |from to| 起始值和结束值| |values |from和to只能指定两个值,使用values时可以以列表形式同时指定多个中间值,变换会依次使用列表内的值。如果要交替动画,则指定为start,end,start三个即可实现| |dur| 持续时间| |fill| 结束时该怎么做,freeze表示冻结,如果不指定会使用默认值:remove,表示动画完成后会返回原始值。| |repeatCount| 动画重复次数| |repeatDur| 重复应该进行多长时间| |calcMode| 过渡类型,可以为线性(linear),直接跳转(不支持过渡时直接跳转到结束值discrete),spline,paced等。|

动画时间与同步动画

SVG动画用到的动画时钟在SVG加载完成时开始启动计时,当用户离开页面时停止计时。因此可以以下列任意一种方式指定动画开始和持续时间为一个数值。

|时间| 说明| |----|----| |时分秒的完整时间值 |例如1:20:23| |分秒形式| 例如02:15| |以h、min、s或者ms结尾的时间值| 例如begin="3.5s" dur="1min" 值和单位之间不能有空格|

可以将一个动画的开始时间设置另一个动画的结束或开始,而不是固定的时间值。

<rect x="10" y="10" width="200" height="25" stroke="black" fill="none">
    <animate 
        id="c1"
        attributeName="width" 
        attributeType="XML" 
        from="200" to="20" 
        begin="0s" dur="5s" 
        fill="freeze">
    </animate>
</rect>
<circle cx="120" cy="60" r="10" stroke="black" fill="none">
    <animate
        attributeName="r"
        attributeType="XML"
        begin="c1.end"
        from="10" to="20"
        dur="4s"
    ></animate>
</circle>

多边形和path动画

多边形和path的值为数字列表,也可以对这些属性进行过渡,但是要保证数字列表中数字的数字数量没有变即可。列表中的每个点都是单独变换的。

<polygon points="30 30 70 30 90 70 10 70" style="fill:#fcc;stroke:black">
    <animate
        attributeName="points"
        attributeType="XML"
        to="50 30 70 50 50 90 30 50"
        begin="0s" dur="5s" fill="freeze"
    ></animate>
</polygon>
<path d="M15 50 Q40 15,50 50,65 32,100 40" style="fill:#fcc;stroke:black" transform="translate(0,50)">
    <animate
        attributeName="d"
        attributeType="XML"
        to="M50 15Q15 40,50 50,32 65,40 100"
        begin="0s" dur="5s" fill="freeze"
    ></animate>
</path>

对坐标变换进行过渡

animate元素不适合对平移、旋转、缩放进行过渡,因为这些坐标变换被包裹在transform属性内。animateTransform元素可以解决这个问题。

<g transform="translate(100,60)">
    <rect x="-10" y="-10" width="20" height="20" style="fill:#ff9;stroke:black">
        <animateTransform
            attributeType="XML"
            attributeName="transform" type="scale"
            from="1" to="4 2"
            dur ="3s"
            begin = "0s" fill="freeze"
        ></animateTransform>
    </rect>
</g>

上述示例中,会对矩形的transform属性进行过渡,通过type指定是对scale进行过渡。可以对矩形进行缩放。缩放的中心为100,60(因为矩形被包裹在g中,g被平移了100,60)

沿着path运动

我们已经可以在animateTransform元素中通过translate对过渡对象进行平移变换,但是如果需要让过渡对象沿着更复杂的路径运动,则需要使用animateMotion元素。

<rect x="-10" y="-10" width="20" height="20" style="fill:#ff9;stroke:black">
    <animateMotion
        path="M50,135C100,25 150,225 200,125"
        dur="6s" fill="freeze"
    ></animateMotion>
</rect>

上述示例中,可以使矩形沿着path="M50,135C100,25 150,225 200,125"做轨迹运动,但是运动过程中,矩形不会自动根据轨迹方向旋转,因此需要设置animateMotion元素的rotate属性值为auto。

CSS处理SVG动画

骤:一是选中要运动的元素,然后设置将动画属性作为一个整体进行设置。二是告诉浏览器改变选中元素的哪个属性以及在动画的什么阶段。这些都定义在@keyframes说明符中。

|动画属性| 说明| |----|----| |animation-name| @keyframes说明符的名称| |animation-duration| 动画持续时长| |animation-timing-function| 如何计算中间值,也就是动画类型:线性,缓入缓出等等| |animation-iteration-count| 重复次数| |animation-direction| 动画是反向还是正向或者交替执行| |animation-play-state| 可以设置为running或paused| |animation-delya| 延迟时间| |animation-fill-mode |动画不再执行时使用什么属性,可以为forwards(结束时属性)、backwards(开始时属性值)、both|

<defs>
    <g id="starDef">
        <circle cx="50" cy="50" r="10"></circle>
</defs>
<use id="star" class="starStyle" xlink:href="#starDef" fill="#008000"></use>

对应的css代码

.starStyle{
    animation-name:starAnim;
    animation-duration: 2s;
    animation-iteration-count: 4;
    animation-direction: alternate;
    animation-timing-function: ease;
    animation-play-state: running; 
@keyframes starAnim{
        fill:red;
        transform: translate(100px,100px);
        fill:green;
        transform: translate(120px,100px);