SVG

可缩放矢量图形(Scalable Vector Graphics,SVG),是一种用来描述二维矢量图形的 XML 标记语言。不同于光栅图像格式(例如 JPG、PNG 用像素值来描绘的矩阵),矢量图放大缩小都不会失真。

SVG 与 Flash 类似,都是用于二维矢量图形,二者的区别在于,SVG 是一个 W3C 标准,基于 XML,是开放的,而 Flash 是封闭的基于二进制格式的。SVG 与其他的 W3C 标准,比如 CSS、DOM 和 SMIL 等能够协同工作。

注意

  • IE9+ 浏览器支持
  • SVG 的元素和属性必须按标准格式书写,因为 XML 是区分大小写的(这一点和html不同)
  • SVG 里的属性值必须用引号引起来,就算是数值也必须这样做。
  • 各浏览器是有差异的,很可能你制作了一个 SVG 图形,并且用一个工具调试正常后,却在另外一个浏览器中无法正常显示。

HTML引用 SVG 的常用方法

  • 直接嵌入 SVG
  • 通过 img 标签
  • JavaScript 动态创建

基本操作API

  • 创建图形
    • document.createElementNS(ns,tagName)
  • 添加图形
    • element.appendChild(childElement)
  • 设置/获取属性
    • element.setAttribute(name,value)
    • element.getAttribute(name)

基本结构

从一个简单的例子开始,看一下下面代码:

AitSchool
<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
  <rect width="100%" height="100%" fill="#F2EFE6" />
  <circle cx="150" cy="100" r="80" fill="#4da1bd" />
  <text x="150" y="110" font-size="20" text-anchor="middle" fill="#fff">AitSchool</text>
</svg>

绘制流程包括以下几步:

  1. svg 根元素

    • 属性 version 和属性 baseProfile 属性是必不可少的,供其它类型的验证方式确定 SVG 版本。
    • width 和 height 属性可设置此 SVG 文档的宽度和高度。
    • 作为 XML 的一种方言,SVG 必须正确的绑定命名空间 (在xmlns属性中绑定)。
  2. 绘制一个完全覆盖图像区域的矩形 rect ,把背景颜色设为灰色。

  3. 绘制一个半径 80px 的 蓝色圆圈 circle 在红色矩形的正中央 (向右偏移150px,向下偏移100px)。

  4. 绘制文字“AitSchool”。文字被填充为白色,通过设置居中的锚点把文字定位到期望的位置。

基本属性

  • fill 属性设置对象内部的颜色
    • fill-rule 用于定义如何给图形重叠的区域上色
    • fill-opacity 控制填充色的不透明度
  • stroke 属性设置绘制对象的线条的颜色
    • stroke-opacity 控制线条的透明度
    • stroke-width 定义了描边的宽度
    • stroke-linecap 它控制边框终点的形状
      • butt 直边结束线段,线段边界90度垂直于描边的方向、贯穿它的终点
      • square 会稍微超出实际路径的范围,超出的大小由stroke-width控制
      • round 边框的终点是圆角,圆角的半径也是由stroke-width控制的
    • stroke-linejoin 控制两条描边线段之间,用什么方式连接
      • miter 默认值,表示用方形画笔在连接处形成尖角
      • round 圆角连接,实现平滑效果
      • bevel 连接处会形成一个斜接
    • stroke-dasharray 将虚线类型应用在描边上
    • stroke-dashoffset 定义虚线开始的位置
<svg width="200" height="150" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <rect x="10" y="10" width="100" height="100" stroke="blue" fill="purple" fill-opacity="0.5" stroke-opacity="0.8"/>
</svg>
<svg width="200" height="150" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <path d="M 10 75 Q 50 10 100 75 T 190 75" stroke="black"
    stroke-linecap="round" stroke-dasharray="5,10,5" fill="none"/>
  <path d="M 10 75 L 190 75" stroke="red"
    stroke-linecap="round" stroke-width="1" stroke-dasharray="5,5" fill="none"/>
</svg>

坐标、视窗、世界、视野

对于所有元素,SVG 使用的坐标系统或者说网格系统。这种坐标系统是:以页面的左上角为(0,0)坐标点,坐标以像素为单位,x轴正方向是向右,y轴正方向是向下。

  • SVG 标签的 width 和 height 控制视窗大小。
  • SVG 里的元素代码内容代表着世界。
  • viewBox、preserveAspectRatio 控制视野
<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
    <rect width="100%" height="100%" fill="#F2EFE6" />
    <circle cx="150" cy="100" r="80" fill="#4da1bd" />
</svg>
  • 定义一个矩形,即从左上角开始,绘制一个 150 * 100 的矩形。
  • 定义一个圆形,右偏移150px,向下偏移100px 的点为圆心,半径为 80 绘制。

viewBox 属性表示 SVG 可见区域的大小,可以改变我们对 SVG 元素里面的能见度。

<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 100">
    <rect width="150" height="100" fill="#F2EFE6" />
    <circle cx="150" cy="100" r="80" fill="#4da1bd" />
</svg>

这里定义的画布尺寸是300 * 200px。但是,viewBox属性定义了画布上可以显示的区域:从(0,0)点开始,150宽 * 100高的区域。这个150 * 100的区域,会放到300 * 200的画布上显示。于是就形成了放大两倍的效果。

preserveAspectRatio

当viewBox 和 SVG 宽高比例不一致时候。可以使用 preserveAspectRatio 属性描述 viewBox 在 SVG 中对其与缩放的展示的方式。preserveAspectRatio属性的值为空格分隔的两个值组合而成。

第1个值表示,viewBox如何与SVG viewport对齐:

横行对齐方式

  • xMin viewport和viewBox左边对齐
  • xMid viewport和viewBox x轴中心对齐
  • xMax viewport和viewBox右边对齐

垂直对齐方式

  • YMin viewport和viewBox上边缘对齐。注意Y是大写。
  • YMid viewport和viewBox y轴中心点对齐。注意Y是大写。
  • YMax viewport和viewBox下边缘对齐。注意Y是大写。

组合

  • none 元素的边界完全匹配视图矩形。
  • xMinYMin
    • 将SVG元素的viewbox属性的X的最小值与视图的X的最小值对齐。
    • 将SVG元素的viewbox属性的Y的最小值与视图的Y的最小值对齐。
  • xMidYMin
    • 将SVG元素的viewbox属性的X的中点值与视图的X的中点值对齐。
    • 将SVG元素的viewbox属性的Y的最小值与视图的Y的最小值对齐。
  • xMaxYMin
    • 将SVG元素的viewbox属性的X的最小值+元素的宽度与视图的X的最大值对齐。
    • 将SVG元素的viewbox属性的Y的最小值与视图的Y的最小值对齐。
  • xMinYMid
    • 将SVG元素的viewbox属性的X的最小值与视图的X的最小值对齐。
    • 将SVG元素的viewbox属性的Y的中点值与视图的Y的中点值对齐。
  • xMidYMid (默认值)
    • 将SVG元素的viewbox属性的X的中点值与视图的X的中点值对齐。
    • 将SVG元素的viewbox属性的Y的中点值与视图的Y的中点值对齐。
  • xMaxYMid
    • 将SVG元素的viewbox属性的X的最小值+元素的宽度与视图的X的最大值对齐。
    • 将SVG元素的viewbox属性的Y的中点值与视图的Y的中点值对齐。
  • xMinYMax
    • 将SVG元素的viewbox属性的X的最小值与视图的X的最小值对齐。
    • 将SVG元素的viewbox属性的Y的最小值+元素的高度与视图的Y的最大值对齐。
  • xMidYMax
    • 将SVG元素的viewbox属性的X的中点值与视图的X的中点值对齐。
    • 将SVG元素的viewbox属性的Y的最小值+元素的高度与视图的Y的最大值对齐。
  • xMaxYMax
    • 将SVG元素的viewbox属性的X的最小值+元素的宽度与视图的X的最大值对齐。
    • 将SVG元素的viewbox属性的Y的最小值+元素的高度与视图的Y的最大值对齐。

第2个值表示,如何维持高宽比(可选):

  • meet 保持纵横比缩放viewBox适应viewport
  • slice 保持纵横比同时比例小的方向放大填满viewport

以下SVG的宽高比为 3:2,viewBox 的为 1:1 。preserveAspectRatio不同情况事例如下:

  • 不设置 preserveAspectRatio ,默认值 xMidYMid meet
<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg" viewBox="70 20 80 80">
    <rect width="150" height="100" fill="#F2EFE6" />
    <circle cx="150" cy="100" r="80" fill="#4da1bd" />
</svg>
  • preserveAspectRatio 为 none ,扭曲纵横比以充分适应
<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg" viewBox="70 20 80 80" preserveAspectRatio="none">
    <rect width="150" height="100" fill="#F2EFE6" />
    <circle cx="150" cy="100" r="80" fill="#4da1bd" />
</svg>
  • preserveAspectRatio 为 xMinYMin meet ,viewport和viewBox,左上两边对齐,保持纵横比缩放viewBox适应viewport。
<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg" viewBox="70 20 80 80" preserveAspectRatio="xMinYMin meet">
    <rect width="150" height="100" fill="#F2EFE6" />
    <circle cx="150" cy="100" r="80" fill="#4da1bd" />
</svg>
  • preserveAspectRatio 为 xMaxYMin meet ,viewport和viewBox,右上两边对齐,保持纵横比缩放viewBox适应viewport。
<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg" viewBox="70 20 80 80" preserveAspectRatio="xMaxYMin meet">
    <rect width="150" height="100" fill="#F2EFE6" />
    <circle cx="150" cy="100" r="80" fill="#4da1bd" />
</svg>

形状

要想插入一个形状,你可以在文档中创建一个元素。不同的元素对应着不同的形状,并且使用不同的属性来定义图形的大小和位置。SVG 一些预定义的形状元素:

  • 矩形 rect
  • 圆形 circle
  • 椭圆 ellipse
  • 线 line
  • 折线 polyline
  • 多边形 polygon
  • 路径 path
<svg width="200" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <!-- 正方形 -->
  <rect x="10" y="10" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"/>
  <rect x="60" y="10" rx="10" ry="10" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"/>
  <!-- 圆形椭圆形 -->
  <circle cx="25" cy="75" r="20" stroke="red" fill="transparent" stroke-width="5"/>
  <ellipse cx="75" cy="75" rx="20" ry="5" stroke="red" fill="transparent" stroke-width="5"/>
  <!-- 线 和 折线 -->
  <line x1="10" x2="50" y1="110" y2="150" stroke="orange" fill="transparent" stroke-width="5"/>
  <polyline points="60 110 65 120 70 115 75 130 80 125 85 140 90 135 95 150 100 145"
      stroke="orange" fill="transparent" stroke-width="5"/>
  <!-- 多边形 -->
  <polygon points="50 160 55 180 70 180 60 190 65 205 50 195 35 205 40 190 30 180 45 180"
      stroke="green" fill="transparent" stroke-width="5"/>
  <!-- 路径 -->
  <path d="M20,230 Q40,205 50,230 T90,230" fill="none" stroke="blue" stroke-width="5"/>
</svg>

矩形

参数:

  • x 矩形左上角的x位置
  • y 矩形左上角的y位置
  • width 矩形的宽度
  • height 矩形的高度
  • rx 圆角的x方位的半径
  • ry 圆角的y方位的半径
<rect x="60" y="10" rx="10" ry="10" width="30" height="30"/>

圆形

参数:

  • r 圆的半径
  • cx 圆心的x位置
  • cy 圆心的y位置
<circle cx="25" cy="75" r="20"/>

椭圆

  • rx 椭圆的x半径
  • ry 椭圆的y半径
  • cx 椭圆中心的x位置
  • cy 椭圆中心的y位置
<ellipse cx="75" cy="75" rx="20" ry="5"/>

线条

它取两个点的位置作为属性,指定这条线的起点和终点位置。

  • x1 起点的x位置
  • y1 起点的y位置
  • x2 终点的x位置
  • y2 终点的y位置
<line x1="10" x2="50" y1="110" y2="150"/>

折线

Polyline是一组连接在一起的直线。因为它可以有很多的点,折线的的所有点位置都放在一个points属性中:每个数字用空白、逗号、终止命令符或者换行符分隔开。每个点必须包含2个数字,一个是x坐标,一个是y坐标。所以点列表 (0,0), (1,1) 和(2,2)可以写成这样:“0 0, 1 1, 2 2”。

<polyline points="60 110, 65 120, 70 115, 75 130, 80 125, 85 140, 90 135, 95 150, 100 145"/>

多边形

polygon和折线很像,它们都是由连接一组点集的直线构成。不同的是,polygon的路径在最后一个点处自动回到第一个点。

<polygon points="50 160, 55 180, 70 180, 60 190, 65 205, 50 195, 35 205, 40 190, 30 180, 45 180"/>

路径

path可能是SVG中最常见的形状。你可以用path元素绘制矩形(直角矩形或者圆角矩形)、圆形、椭圆、折线形、多边形,以及一些其他的形状,例如贝塞尔曲线、2次曲线等曲线。

  • d 一个点集数列以及其它关于如何绘制路径的信息,是一个“命令+参数”的序列。
<path d="M 20 230 Q 40 205, 50 230 T 90230"/>

每一个命令都用一个关键字母来表示,比如,字母“M”表示的是“Move to”命令,当解析器读到这个命令时,它就知道你是打算移动到某个点。跟在命令字母后面的,是你需要移动到的那个点的x和y轴坐标。比如移动到(10,10)这个点的命令,应该写成“M 10 10”。这一段字符结束后,解析器就会去读下一段命令。每一个命令都有两种表示方式,一种是用大写字母,表示采用绝对定位。另一种是用小写字母,表示采用相对定位(例如:从上一个点开始,向上移动10px,向左移动7px)。

  • 直线命令 M x y
  • 曲线命令 C x1 y1, x2 y2, x y
  • 弧形 A rx ry x-axis-rotation large-arc-flag sweep-flag x y

命令信息

分组

g 标签创建分组,属性定义坐标变换

<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
    <g stroke="green" fill="#4da1bd" >
      <rect x="100" y="50" width="100" height="50" />
      <rect x="140" y="100" width="20" height="120"/>
    </g>
</svg>

渐变

线性渐变

线性渐变沿着直线改变颜色,要插入一个线性渐变,你需要在 SVG 文件的 defs 元素内部,创建一个 linearGradient 节点。

线性渐变内部有几个 stop 结点,这些结点通过指定位置的 offset(偏移)属性和 stop-color(颜色中值)属性来说明在渐变的特定位置上应该是什么颜色;可以直接指定这两个属性值,也可以通过CSS来指定他们的值。

gradientUnits 属性的默认值为 objectBoundingBox 用包容的盒子来描述。当值为 userSpaceOnUse 时,用户可自定义渐变坐标范围。这时候 x1、y1、x2、y2 相对SVG画布的开始点和结束点坐标。

<svg width="400" height="150" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
      <linearGradient id="Gradient1" gradientUnits="objectBoundingBox">
        <stop offset="0%" stop-color="#1497fc"/>
        <stop offset="50%" stop-color="#a469be"/>
        <stop offset="100%" stop-color="#ff8c00"/>
      </linearGradient>
      <linearGradient id="Gradient2" gradientUnits="userSpaceOnUse" x1="150" y1="0" x2="350" y2="150">
        <stop offset="0%" stop-color="#1497fc"/>
        <stop offset="50%" stop-color="#a469be"/>
        <stop offset="100%" stop-color="#ff8c00"/>
      </linearGradient>
  </defs>
  <rect rx="15" ry="15" width="150" height="150" fill="url(#Gradient1)"/>
  <rect x="200" y="0" rx="15" ry="15" width="150" height="150"  fill="url(#Gradient2)"/>
</svg>

径向渐变

径向渐变与线性渐变相似,只是它是从一个点开始发散绘制渐变。创建径向渐变需要在文档的defs中添加一个 radialGradient 元素。

  • cx、cy 表示渐变开始的坐标
  • r 表示半径
  • fx、fy 表示焦点的坐标。
<svg width="400" height="150" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
      <radialGradient id="Gradient3" cx="0.5" cy="0.5" r="0.5">
        <stop offset="0%" stop-color="#1497fc"/>
        <stop offset="50%" stop-color="#a469be"/>
        <stop offset="100%" stop-color="#ff8c00"/>
      </radialGradient>
      <radialGradient id="Gradient4" cx="0.5" cy="0.5" r="0.5" fx="0.8" fy="0.8">
        <stop offset="0%" stop-color="#1497fc"/>
        <stop offset="50%" stop-color="#a469be"/>
        <stop offset="100%" stop-color="#ff8c00"/>
      </radialGradient>
  </defs>
  <rect rx="15" ry="15" width="150" height="150" fill="url(#Gradient3)"/>
  <rect x="200" y="0" rx="15" ry="15" width="150" height="150"  fill="url(#Gradient4)"/>
</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。

创建文本标签

使用 text、tspan 创建文本,使用 textpath创建路径文本

  • x、y 定位
  • dx、dy 偏移
  • style 设置样式
  • text-anchor 文本流水平的对齐方向。(start|middle|end|inherit)
  • dominant-baseline 文本流垂直对齐方向。(...)
  • textpath 中,超出路径的文字将不再进行渲染,可以通过 startOffset 属性控制开始位置
  • 可以使用 a 标签定义超链接,可以添加到任何图形上
MiddleMiddleMiddleABCDHello,AitSchool!0123456789
<svg width="400" height="150" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
      <pattern id="grid" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
        <path stroke="#e4e4e4" fill="none" d="M0,0H20V20V"></path>
      </pattern>
  </defs>
  <!-- 定义网格 -->
  <rect width="400" height="150" fill="url(#grid)"/>
  <!-- 定义参照线 -->
  <path d="M100,0V200M0,100H200" stroke="red" />
  <!-- 定义文本路径 -->
  <path id="textpath_path_1" d="M 10 20 Q 20 10 30 20 T 50 20" stroke="red" fill="none"/>
  <!-- 定义文本,水平对齐 -->
  <text x="100" y="20" text-anchor="start">start</text>
  <text x="100" y="40" text-anchor="middle">Middle</text>
  <text x="100" y="60" text-anchor="end">end</text>
  <!-- 定义文本,垂直对齐 -->
  <text x="100" y="100">A</text>
  <text x="120" y="100" dominant-baseline="hanging">B</text>
  <text x="140" y="100" dominant-baseline="middle">C</text>
  <text x="160" y="100" dominant-baseline="central">D</text>
  <text x="100" y="100" dx="20" dy="40" style="font-size:20px;">Hello,AitSchool!</text>
  <!-- 定义路金文本 -->
  <text>
    <textPath startOffset="20%" xlink:href="#textpath_path_1" style="font-size: 12px;">0123456789</textPath>
  </text>
  <!-- 定义超链接 -->
  <a xlink:href="https://www.baidu.com" xlink:title="点我跳百度" target="_blank">
    <rect x="300" y="0" width="100" height="100" fill="blue"/>
  </a>
</svg>

图形引用

use 标签创建图形引用,使用 xlink:href 属性引用一个具有一个唯一的ID属性和重复的图形元素。

<svg width="400" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg" >
  <!-- 绘制背景 -->
  <rect  width="100%" height="100%"  fill="#333" />
  <g id="star-group">
    <defs>
      <!-- 绘制多边形星星 -->
      <polygon id="star" points="0 -10 2 -2 10 0 2 2 0 10 -2 2 -10 0 -2 -2" fill="white" />
    </defs>
    <!-- 多次引用星星 -->
    <use xlink:href="#star" x="60" y="150"/>
    <use xlink:href="#star" x="80" y="80" />
    <use xlink:href="#star" x="150" y="30"/>
    <use xlink:href="#star" x="200" y="120"/>
    <use xlink:href="#star" x="350" y="120"/>
  </g>
</svg>

使用 polygon 绘制出星星,然后使用 use 标签对星星进行不断的引用。通过JS甚至可以创造出众多不同位置、不同大小、透明度不一的星星 ✨。

剪切

clipPath 用来移除在别处定义的元素的部分内容。在这里,任何半透明效果都是不行的。它只能要么显示要么不显示。

  • 我们先绘制以下几个图形,分别是灯塔、灯光、还有灯光范围。
<svg width="400" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg" >
  <!-- 绘制背景 -->
  <rect  width="100%" height="100%"  fill="#333" />
  <!-- 灯塔分组 -->
  <g id="light-tower" transform="translate(300, 150)">
    <!-- 灯光射线 -->
    <polygon points="0 0 -120 -15 -120  15" fill="rgba(255,255,255,0.5)"></polygon>
    <!-- 灯塔三角形 -->
    <polygon points="0 0 5 50 -5 50" fill="rgba(255,255,255,.5)"/>
    <!-- 灯塔原点灯 -->
    <circle cx="0" cy="0" r="2" fill="rgba(255,255,255,.5)"></circle>
    <!-- 灯光范围 -->
    <ellipse cx="0" cy="0" rx="100" ry="50" fill="rgba(255,255,255,.5)"></ellipse>
  </g>
</svg>
  • 我们希望显示灯光和灯光范围重叠的部分,并在 fill 上填充进渐变背景图像。使用 clipPath 创建剪裁区,然后在灯光范围椭圆元素内使用 clip-path 引用。
<svg width="400" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg" >
  <rect  width="100%" height="100%"  fill="#333" />
  <g id="light-tower" transform="translate(300, 150)">
    <defs>
      <!-- 灯塔渐变颜色 -->
      <linearGradient id="tower">
        <stop offset="0" stop-color="#999"></stop>
        <stop offset="1" stop-color="#333"></stop>
      </linearGradient>
      <!-- 灯光径向渐变颜色 -->
      <radialGradient id="light" cx="0.5" cy="0.5" r="0.5">
        <stop offset="0" stop-color="rgba(255,255,255,0.6)"></stop>
        <stop offset="1" stop-color="rgba(255,255,255,0)"></stop>
      </radialGradient>
      <!-- 裁切 -->
      <clipPath id="light-mask">
        <!-- 灯光射线 -->
        <polygon points="0 0 -120 -15 -120  15" fill="rgba(255,0,0,0.5)">
          <!-- 动画 -->
          <animateTransform 
            attributeName="transform" 
            attributeType="XML" 
            type="rotate" 
            from="0" 
            to="360" 
            dur="10s" 
            repeatCount="indefinite">
          </animateTransform>
        </polygon>
        <!-- 灯塔原点 -->
        <circle cx="0" cy="0" r="2"></circle>
      </clipPath>
    </defs>
    <!-- 灯塔 -->
    <polygon points="0 0 5 50 -5 50" fill="url(#tower)"/>
    <!-- 灯光 -->
    <ellipse cx="0" cy="0" 
      rx="100" ry="50" 
      fill="url(#light)" 
      clip-path="url(#light-mask)"></ellipse>
  </g>
</svg>

遮罩

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

<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>

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

  • 首先创建出两个圆形区域。
<svg width="400" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg" >
  <rect  width="100%" height="100%"  fill="#333" />
  <g id="moon-group">
    <circle cx="80" cy="80" r="40" fill="rgba(255,255,255,0.5)"></circle>
    <circle cx="100" cy="60" r="40" fill="rgba(255,255,255,0.5)"></circle>
  </g>
</svg>
  • 以创建的区域添加到遮罩的区域

事例

<svg width="400" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg" >
  <!-- 背景 -->
  <rect  width="100%" height="100%"  fill="#333" />
  <!-- 星星 -->
  <g id="star-group">
    <defs>
      <polygon id="star" 
        points="0 -10 2 -2 10 0 2 2 0 10 -2 2 -10 0 -2 -2" 
        fill="white" />
    </defs>
    <use xlink:href="#star" x="60" y="150"/>
    <use xlink:href="#star" x="80" y="80" />
    <use xlink:href="#star" x="150" y="30"/>
    <use xlink:href="#star" x="200" y="120"/>
    <use xlink:href="#star" x="350" y="120"/>
  </g>
  <!-- 灯塔 -->
  <g id="light-tower" transform="translate(300, 150)">
    <defs>
      <linearGradient id="tower">
        <stop offset="0" stop-color="#999"></stop>
        <stop offset="1" stop-color="#333"></stop>
      </linearGradient>
      <radialGradient id="light" cx="0.5" cy="0.5" r="0.5">
        <stop offset="0" stop-color="rgba(255,255,255,0.6)"></stop>
        <stop offset="1" stop-color="rgba(255,255,255,0)"></stop>
      </radialGradient>
      <clipPath id="light-mask">
        <polygon points="0 0 -120 -15 -120  15" fill="rgba(255,0,0,0.5)">
          <animateTransform attributeName="transform" 
            attributeType="XML" 
            type="rotate" 
            from="0" 
            to="360" 
            dur="10s" 
            repeatCount="indefinite">
          </animateTransform>
        </polygon>
        <circle cx="0" cy="0" r="2"></circle>
      </clipPath>
    </defs>
    <polygon points="0 0 5 50 -5 50" fill="url(#tower)" x="100" y="100"/>
    <ellipse cx="0" cy="0" 
      rx="100" ry="50" 
      fill="url(#light)" 
      clip-path="url(#light-mask)">
    </ellipse>
  </g>
  <!-- 月亮 -->
  <g id="moon-group">
    <mask id="moon-mask">
      <circle cx="80" cy="80" r="40" fill="yellow"></circle>
      <circle cx="100" cy="60" r="40" fill="black"></circle>
    </mask>
    <circle cx="80" cy="80" r="40" fill="yellow" mask="url(#moon-mask)"></circle>
  </g>
</svg>

变形

  • 平移 你能把元素移动一段距离,甚至你可以根据相应的属性定位它。translate()变形方法专门效力于这个目的。
<rect x="0" y="0" width="10" height="10" transform="translate(30,40)" />
  • 旋转
<rect x="20" y="20" width="20" height="20" transform="rotate(45)" />

参考