SVG进阶教程全攻略

前面分享过一篇基础svg的,这篇分享一些高级的SVG教程,比如SVG路径中的三次贝塞尔曲线、椭圆弧线、SVG文本和填充效果等。

一.SVG路径

(一)直线命令
path元素里有5个画直线的命令,顾名思义,直线命令就是在两个点之间画直线。首先是“Move to”命令,M,前面已经提到过,它需要两个参数,分别是需要移动到的点的x轴和y轴的坐标。假设,你的画笔当前位于一个点,在使用M命令移动画笔后,只会移动画笔,但不会在两点之间画线。因为M命令仅仅是移动画笔,但不画线。所以M命令经常出现在路径的开始处,用来指明从何处开始画。
为了更好地展示路径,下面的所有例子里,在用path绘制路径的同时,也会用circle标注路径上的点。

<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path d="M10 10"/>
  <!-- Points -->
  <circle cx="10" cy="10" r="2" fill="red"/>
</svg>

能够真正画出线的命令有三个(M命令是移动画笔位置,但是不画线),最常用的是“Line to”命令,L,L需要两个参数,分别是一个点的x轴和y轴坐标,L命令将会在当前位置和新位置(L前面画笔所在的点)之间画一条线段。

L x y (or l dx dy)

另外还有两个简写命令,用来绘制平行线和垂直线。H,绘制平行线。V,绘制垂直线。这两个命令都只带一个参数,标明在x轴或y轴移动到的位置,因为它们都只在坐标轴的一个方向上移动。

H x (or h dx)
 V y (or v dy)

最后,我们可以通过一个“闭合路径命令”Z来简化上面的path,Z命令会从当前点画一条直线到路径的起点,尽管我们不总是需要闭合路径,但是它还是经常被放到路径的最后。另外,Z命令不用区分大小写。

Z (or z)

画一个80*80的正方形实例

11111101

运行结果.png
<path d="M10 10 H 90 V 90 H 10 Z" fill="transparent" stroke="black"/>

移动画笔到(10,10)位置出发,绘制水平线到指定的 90 位置,绘制竖直线到指定的 90 位置 ,绘制水平线到指定的 10 位置,闭合路径(回到原点)。

(二)三次贝塞尔曲线指令 (C,S)
曲线指令一共有三组,和直线指令一样,指令字母大写表示坐标位置是绝对坐标,指令字母小写表示坐标位置是相对坐标。三次贝塞尔曲线指令 (C,c,S,s)是其中的一个。

可以通过定义一个起点和终点,以及两个控制点(一个控制起点,一个控制终点),绘制一条贝塞尔曲线。

三次贝塞尔曲线指令的格式为:

C (or c) x1,y1 x2,y2 x,y

x1,y1 是曲线起点的控制点坐标
x2,y2 是曲线终点的控制点坐标
x,y 是曲线的终点坐标

你可以将若干个贝塞尔曲线连起来,从而创建出一条很长的平滑曲线。通常情况下,一个点某一侧的控制点是它另一侧的控制点的对称(以保持斜率不变)。这样,你可以使用一个简写的贝塞尔曲线命令S,如下所示:

S x2 y2, x y (or s dx2 dy2, dx dy)

S命令可以用来创建与之前那些曲线一样的贝塞尔曲线,但是,如果S命令跟在一个C命令或者另一个S命令的后面,它的第一个控制点,就会被假设成前一个控制点的对称点。如果S命令单独使用,前面没有C命令或者另一个S命令,那么它的两个控制点就会被假设为同一个点。下面是S命令的语法示例,下图中的某个控制点用红色标示,与它对称的控制点用蓝色标示。

10101001

运行结果.png

(三)二次贝塞尔曲线指令 (Q,T)

二次贝塞尔曲线Q,它比三次贝塞尔曲线简单,只需要一个控制点,用来确定起点和终点的曲线斜率。因此它需要两组参数,控制点和终点坐标。

Q x1 y1, x y (or q dx1 dy1, dx dy)
12121201

image.png

就像三次贝塞尔曲线有一个S命令,二次贝塞尔曲线有一个差不多的T命令,可以通过更简短的参数,延长二次贝塞尔曲线。

T x y (or t dx dy)

和三次贝塞尔曲线指令 S一样,快捷命令T会通过前一个控制点,推断出一个新的控制点。这意味着,在你的第一个控制点后面,可以只定义终点,就创建出一个相当复杂的曲线。需要注意的是,T命令前面必须是一个Q命令,或者是另一个T命令,才能达到这种效果。如果T单独使用,那么控制点就会被认为和终点是同一个点,所以画出来的将是一条直线。

<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path d="M10 80 Q 52.5 10, 95 80 T 180 80" stroke="black" fill="transparent"/>
</svg>
14141401

运行结果.png

(四)椭圆弧线 (A)

弧形命令A是另一个创建SVG曲线的命令。基本上,弧形可以视为圆形或椭圆形的一部分。假设,已知椭圆形的长轴半径和短轴半径,另外已知两个点(它们的距离在圆的半径范围内),这时我们会发现,有两个路径可以连接这两个点。每种情况都可以生成出四种弧形。所以,为了保证创建的弧形唯一,A命令需要用到比较多的参数:

A rx ry x-axis-rotation large-arc-flag sweep-flag x y
 a rx ry x-axis-rotation large-arc-flag sweep-flag dx dy

弧线命令:

rx – (radius-x)弧线所在椭圆的 x 半轴长
ry – (radius-y)弧线所在椭圆的 y 半轴长
xr – (xAxis-rotation)弧线所在椭圆的长轴角度
laf – (large-arc-flag)是否选择弧长较长的那一段弧
sf – (sweep-flag)是否选择逆时针方向的那一段弧
x, y – 弧的终点位置

13131301

image.png

如上图例所示,画布上有一条对角线,中间有两个椭圆弧被对角线切开(x radius = 30, y radius = 50)。第一个椭圆弧的x-axis-rotation(x轴旋转角度)是0,所以弧形所在的椭圆是正置的(没有倾斜)。在第二个椭圆弧中,x-axis-rotation设置为-45,所以这是一个旋转了45度的椭圆,并以短轴为分割线,形成了两个对称的弧形。参看图示中的第二个椭圆形。

如前所讲,还有两种可能的椭圆用来形成路径,它们给出的四种可能的路径中,有两种不同的路径。这里要讲的参数是large-arc-flag(角度大小) 和sweep-flag(弧线方向),large-arc-flag决定弧线是大于还是小于180度,0表示小角度弧,1表示大角度弧。sweep-flag表示弧线的方向,0表示从起点到终点沿逆时针画弧,1表示从起点到终点沿顺时针画弧。下面的例子展示了这四种情况。

<svg width="325px" height="325px" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path d="M80 80
           A 45 45, 0, 0, 0, 125 125
           L 125 80 Z" fill="green"/>
  <path d="M230 80
           A 45 45, 0, 1, 0, 275 125
           L 275 80 Z" fill="red"/>
  <path d="M80 230
           A 45 45, 0, 0, 1, 125 275
           L 125 230 Z" fill="purple"/>
  <path d="M230 230
           A 45 45, 0, 1, 1, 275 275
           L 275 230 Z" fill="blue"/>
</svg>
15151501

运行结果.png

二.SVG文本

(一)< text > 及其属性
在SVG中有两种截然不同的文本模式. 一种是写在图像中的文本,另一种是SVG字体。现在我们主要集中前者:写在图像中的文本。在一个SVG文档中,元素内部可以放任何的文字。

<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
    <text x="100" y="100" font-weight="bold" fill="red" font-size="30">Hello 简书</text>
</svg>
16161601

运行结果.png

属性x和属性y性决定了文本在视口中显示的位置。属性text-anchor,可以有这些值:start、middle、end或inherit,允许决定从这一点开始的文本流的方向。和形状元素类似,属性fill可以给文本填充颜色,属性stroke可以给文本描边,形状元素和文本元素都可以引用渐变或图案, 相比较CSS2.1只能绘制简单的彩色文字,SVG显得更具有优势。

设置字体属性
文本的一个至关重要的部分是它显示的字体。SVG提供了一些属性,类似于它们的CSS同行,用来激活文本选区。下列每个属性可以被设置为一个SVG属性或者成为一个CSS声明:font-family、font-style、font-weight、font-variant、font-stretch、font-size、font-size-adjust、kerning、letter-spacing、word-spacing和text-decoration。

(二)tspan
tspan元素用来标记大块文本的子部分,它必须是一个text元素或别的tspan元素的子元素。一个典型的用法是把句子中的一个词变成粗体红色。

<text>
  <tspan font-weight="bold" fill="red">This is bold and red</tspan>
</text>
17171701

运行结果.png

(三)路径文本
除了笔直地绘制一行文字以外, SVG 也可以根据 < path > 元素的形状来放置文字。 只要在textPath元素内部放置文本,并通过其xlink:href属性值引用< path > 元素,我们就可以让文字块呈现在< path > 元素给定的路径上了。

使用方法:

<path id="my_path" d="M 100 200 Q 200 100 300 200 T 500 200" stroke="rgb(0,255,0)" fill="none" />
<text>
  <textPath xlink:href="#my_path">This text follows a curve.</textPath>
</text>
18181801

运行结果.png

startOffset 属性 确定排列起始
dx, dy 属性 切线和法线方向的偏移

(四)< a > – 超链接
可以添加到任意的图形上

属性
xlink:href 指定连接地址
xlink:title 指定连接提示
target 指定打开目标

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
  <a xlink:href="http://www.jianshu.com" xlink:title="打开简书"  target="_blank">
    <text x="0" y="15" fill="red">I love 简书</text>
  </a>
</svg>
19191901

运行结果.png

三.剪切和遮罩

(一)创建剪切
clip-path属性是指定一个应用到元素上的剪切路径。应用在SVG中 < clipPath > 元素上的属性值可以完全运用在clip-path的属性上。

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <clipPath id="cut-off-bottom">
      <rect x="0" y="0" width="200" height="100" />
    </clipPath>
  </defs>

  <circle cx="100" cy="100" r="100" clip-path="url(#cut-off-bottom)" />
</svg>
21212102

运行结果.png

在(100,100)创建一个圆形,半径是100。属性clip-path引用了一个带单个rect元素的< clipPath >元素。它内部的这个矩形将把画布的上半部分涂黑。

注意:clipPath元素经常放在一个defs元素内。
然而,该rect不会被绘制。它的象素数据将用来确定:圆形的哪些像素需要最终呈现出来。因为矩形只覆盖了圆形的上半部分,所以下半部分将消失了(右图示例);现在我们已经有了一个半圆形,不用处理弧形路径元素。对于这个剪切,clipPath内部的每个路径都会被检查到、与它的描边属性一起被估值、变形。然后目标的位于clipPath内容的结果的透明度区域的每一块都不会呈现。颜色、不透明度都没有这种效果,因为它们不能让一部分彻底消失。

(二)遮罩
遮罩的效果最令人印象深刻的是表现为一个渐变。如果你想要让一个元素淡出,你可以利用遮罩效果实现这一点。

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <linearGradient id="Gradient">
      <stop offset="0" stop-color="white" stop-opacity="0" />
      <stop offset="1" stop-color="white" stop-opacity="1" />
    </linearGradient>
    <mask id="Mask">
      <rect x="0" y="0" width="200" height="200" fill="url(#Gradient)"  />
    </mask>
  </defs>

  <rect x="0" y="0" width="200" height="200" fill="green" />
  <rect x="0" y="0" width="200" height="200" fill="red" mask="url(#Mask)" />
</svg>
20202002

运行结果.png

你看到有一个绿色填充的矩形在底层,一个红色填充的矩形在上层。后者有一个mask属性指向一个mask元素。mask元素的内容是一个单一的rect元素,它填充了一个透明到白色的渐变。作为红色矩形继承mark内容的alpha值(透明度)的结果,我们看到一个从绿色到红色渐变的输出(右图)。

(三)用opacity定义透明度
有一个简单方法可以用来为整个元素设置透明度。它就是opacity属性:

<rect x="0" y="0" width="100" height="100" opacity=".5" />

上面的矩形将绘制为半透明。还有两个分开的属性fill-opacity和stroke-opacity,分别用来控制填充和描边的不透明度。注意,描边将绘制在填充的上面。因此,如果你在元素上设置了一个描边透明度,它同时还有填充,则填充将在描边上透过一半,另一半背景也将出现:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <rect x="0" y="0" width="200" height="200" fill="blue" />
  <circle cx="100" cy="100" r="50" stroke="yellow" stroke-width="40" stroke-opacity=".5" fill="red" />
</svg>
22222202

运行结果.png
原文:http://www.jianshu.com/p/ae87e188b44b

关注我

我的微信公众号:前端开发博客,在后台回复以下关键字可以获取资源。

  • 回复「小抄」,领取Vue、JavaScript 和 WebComponent 小抄 PDF
  • 回复「Vue脑图」获取 Vue 相关脑图
  • 回复「思维图」获取 JavaScript 相关思维图
  • 回复「简历」获取简历制作建议
  • 回复「简历模板」获取精选的简历模板
  • 回复「加群」进入500人前端精英群
  • 回复「电子书」下载我整理的大量前端资源,含面试、Vue实战项目、CSS和JavaScript电子书等。
  • 回复「知识点」下载高清JavaScript知识点图谱

每日分享有用的前端开发知识,加我微信:caibaojian89 交流