日记

日记

  • Diary
  • GitHub

›All Blog Posts

All Blog Posts

  • 再看高程3
  • 面试
  • 个人简历
  • react的高性能
  • webpack源码学习
  • 树莓派
  • 布局
  • 模块化
  • 攻击与安全
  • 异步
  • TODO
  • React状态管理比较
  • 性能优化
  • HTTP缓存
  • (译)JS中数据的改变与发现
  • CSS杂记
  • XML与SVG
  • 个人简历
  • Workspaces是什么
  • NPM包测试之低高级策略
  • 谈谈version
  • 减肥之道
  • 问题汇总
  • 一个nginx配置
  • 好用的工具
  • 好用的npm包
  • 流行框架学习对比

XML与SVG

June 20, 2018

Shiyong Yin

XML简介

XML被设计用来传输和存储数据

HTML被设计用来显示数据

XMLHttpRequest是XML的衍生体,它不仅能从服务器取回数据,也能读取本地的xml文件

SVG简单示例

SVG的元素和属性必须按标准格式书写,因为XML是区分大小写的(这一点和html不同)

SVG里的属性值必须用引号引起来,就算是数值也必须这样做。

<?xml version="1.0" standalone="no"?>
<svg
  version="1.1"
  baseProfile="full"
  width="300" height="200"
  xmlns="http://www.w3.org/2000/svg">
  <rect width="100%" height="100%" fill="red" />
  <circle cx="150" cy="100" r="80" fill="green" />
  <text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>
</svg>
SVG

HTML中如何引入SVG

  • 如果HTML是XHTML并且声明类型为application/xhtml+xml,可以直接把SVG嵌入到XML源码中
  • 如果HTML是HTML5并且浏览器支持HTML5,同样可以直接嵌入SVG。然而为了符合HTML5标准,可能需要做一些语法调整。
  • 可以通过 object 元素引用SVG文件
  • 类似的也可以使用 iframe 元素引用SVG文件:
  • 理论上同样可以使用 img 元素,但是在低于4.0版本的Firefox 中不起作用。
  • 最后SVG可以通过JavaScript动态创建并注入到HTML DOM中。 这样具有一个优点,可以对浏览器使用替代技术,在不能解析SVG的情况下,可以替换创建的内容。

服务器返回头部信息

  • Content-Type: image/svg+xml

什么是像素

基本上,在 SVG 文档中的1个像素对应输出设备(比如显示屏)上的1个像素。但是这种情况是可以改变的,否则 SVG 的名字里也不至于会有“Scalable”(可缩放)这个∫词

基本图形

<?xml version="1.0" standalone="no"?>
<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>

矩形 rect

  • x
    • 起点x坐标
  • y
    • 起点y坐标
  • rx
    • 圆角x方位的半径
  • ry
    • 圆角方位的半径
  • width
    • x 方向宽度
  • height
    • y 方向高度

圆形 circle

  • cx
    • 圆心x的位置
  • cy
    • 圆心y的位置

椭圆 ellipse

  • rx
    • 椭圆x的半径
  • ry
    • 椭圆y的半径
  • cx
    • 椭圆心x的位置
  • cy
    • 椭圆心y的位置

折现 polyline

  • points
    • 点集数列。每个数字用空白、逗号、终止命令符或者换行符分隔开。每个点必须包含2个数字,一个是x坐标,一个是y坐标。所以点列表 (0,0), (1,1) 和(2,2)可以写成这样:“0 0, 1 1, 2 2”。

多边形 polygon

  • points
    • 点集数列。每个数字用空白符、逗号、终止命令或者换行符分隔开。每个点必须包含2个数字,一个是x坐标,一个是y坐标。所以点列表 (0,0), (1,1) 和(2,2)可以写成这样:“0 0, 1 1, 2 2”。路径绘制完后闭合图形,所以最终的直线将从位置(2,2)连接到位置(0,0)。

路径 path

  • d
    • 属性d的值是一个“命令+参数”的序列

直线路径

直线命令

  • M: Move to 因为M命令仅仅是移动画笔,但不画线。所以M命令经常出现在路径的开始处,用来指明从何处开始画。
  • 能够真正画出线的命令有三个
    • L L需要两个参数,分别是一个点的x轴和y轴坐标
    • H 水平线
    • V 垂直线
  • Z Z命令会从当前点画一条直线到路径的起点
<?xml version="1.0" standalone="no"?>
<svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path d="M10 10 H 90 V 90 H 10 z" stroke-width="5" fill="transparent" stroke="blue"></path>
  <circle cx="10" cy="10" r="2" fill="red"/>
  <circle cx="90" cy="90" r="2" fill="red"/>
  <circle cx="90" cy="10" r="2" fill="red"/>
  <circle cx="10" cy="90" r="2" fill="red"/>
</svg>

曲线路径

绘制平滑曲线的命令有三个,其中两个用来绘制贝塞尔曲线,另外一个用来绘制弧形或者说是圆的一部分

贝塞尔曲线的类型有很多,但是在path元素里,只存在两种贝塞尔曲线:三次贝塞尔曲线C,和二次贝塞尔曲线Q。

贝塞尔曲线 CSQT

4个命令

  • C C(第一个控制点,第二个控制点,终点)
    • 三次贝塞尔曲线需要定义一个点和两个控制点,所以用C命令创建三次贝塞尔曲线,需要设置三组坐标参数
  • S S(第二个控制点,终点)
    • S命令可以用来创建与之前那些曲线一样的贝塞尔曲线
      • 如果S命令跟在一个C命令或者另一个S命令的后面,它的第一个控制点,就会被假设成前一个控制点的对称点
      • 如果S命令单独使用,前面没有C命令或者另一个S命令,那么它的两个控制点就会被假设为同一个点
  • Q Q(控制点,终点)
    • 它比三次贝塞尔曲线简单,只需要一个控制点,用来确定起点和终点的曲线斜率。因此它需要两组参数,控制点和终点坐标。
  • T T(终点)
    • 就像三次贝塞尔曲线有一个S命令,二次贝塞尔曲线有一个差不多的T命令,可以通过更简短的参数,延长二次贝塞尔曲线
C x1 y1, x2 y2, x y (or c dx1 dy1, dx2 dy2, dx dy)

这里的最后一个坐标(x,y)表示的是曲线的终点,另外两个坐标是控制点,(x1,y1)是起点的控制点,(x2,y2)是终点的控制点

C示例

<?xml version="1.0" standalone="no"?>
<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/>
  <path d="M70 10 C 70 20, 120 20, 120 10" stroke="black" fill="transparent"/>
  <path d="M130 10 C 120 20, 180 20, 170 10" stroke="black" fill="transparent"/>
  <path d="M10 60 C 20 80, 40 80, 50 60" stroke="black" fill="transparent"/>
  <path d="M70 60 C 70 80, 110 80, 110 60" stroke="black" fill="transparent"/>
  <path d="M130 60 C 120 80, 180 80, 170 60" stroke="black" fill="transparent"/>
  <path d="M10 110 C 20 140, 40 140, 50 110" stroke="black" fill="transparent"/>
  <path d="M70 110 C 70 140, 110 140, 110 110" stroke="black" fill="transparent"/>
  <path d="M130 110 C 120 140, 180 140, 170 110" stroke="black" fill="transparent"/>
</svg>

S示例

<?xml version="1.0" standalone="no"?>
<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="black" fill="transparent"/>
  <circle cx="10" cy="80" r="2" fill="red"/>
  <circle cx="40" cy="10" r="2" fill="red"/>
  <path d="M 10 80 L 40 10" stroke="red"/>
  <circle cx="65" cy="10" r="2" fill="red"/>
  <circle cx="95" cy="80" r="2" fill="red"/>
  <path d="M 65 10 L 95 80" stroke="red"/>
  <circle cx="150" cy="150" r="2" fill="red"/>
  <circle cx="125" cy="150" r="2" fill="red"/>
  <path d="M 95 80 L 125 150" stroke="blue"/>
  <path d="M 150 150 L 180 80" stroke="blue"/>
</svg>
<?xml version="1.0" standalone="no"?>
<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path d="M10 80 S 40 10, 95 80" stroke="black" fill="transparent"/>
  <circle cx="10" cy="80" r="2" fill="red"/>
  <circle cx="40" cy="10" r="2" fill="red"/>
  <circle cx="95" cy="80" r="2" fill="red"/>
  <path d="M10 80 L 40 10" stroke="red"/>
  <path d="M95 80 L 40 10" stroke="red"/>
</svg>

相同的起始点和终点,相同的控制点,在三次和二次赛贝尔曲线中勾画出来的图形不一样

Q示例

<?xml version="1.0" standalone="no"?>
<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg"">
  <path d="M10 80 Q 95 10 180 80" stroke="black" fill="transparent"/>
</svg>

T示例

<?xml version="1.0" standalone="no"?>
<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>

弧形 A

已知椭圆形的长轴半径和短轴半径,并且已知两个点(在椭圆上),根据半径和两点,可以画出两个椭圆,在每个椭圆上根据两点都可以画出两种弧形。所以,仅仅根据半径和两点,可以画出四种弧形。为了保证创建的弧形唯一,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 x半径
  • ry y半径
  • x-axis-rotation 弧形旋转情况(如下图第一个弧形的椭圆旋转0,第二个旋转-45)
  • large-arc-flag 角度大小
  • sweep-falg 弧线方向
  • x 弧形起点
  • y 弧形终点
<?xml version="1.0" standalone="no"?>
<svg width="320px" height="320px" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path d="M10 315
           L 110 215
           A 30 50 0 0 1 162.55 162.45
           L 172.55 152.45
           A 30 50 -45 0 1 215.1 109.9
           L 315 10" stroke="black" fill="green" stroke-width="2" fill-opacity="0.5"/>
</svg>
<?xml version="1.0" standalone="no"?>
<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>

Fill和Stroke属性

fill属性设置对象内部的颜色

stroke属性设置绘制对象的线条的颜色

上色 fill stroke

<svg>
<rect x="10" y="10" width="100" height="100" stroke="blue" fill="purple"
       fill-opacity="0.5" stroke-opacity="0.8"/>
</svg>

描边 stroke-line(cap|join|dasharray)

除了颜色属性,还有其他一些属性用来控制绘制描边的方式

  • stroke-linecap 描边是以路径为中心线绘制的
    • butt 用直边结束线段
    • square 稍微超出实际路径的范围,超出的大小由stroke-width控制
    • round 示边框的终点是圆角,圆角的半径也是由stroke-width控制的
  • stroke-linejoin 每条折线都是由两个线段连接起来的,连接处的样式由stroke-linejoin属性控制
    • miter 尖角
    • round 圆角
    • bevel 平滑
  • stroke-linedasharray 将虚线类型应用在描边上
    • stroke-dasharray属性的参数,是一组用逗号分割的数字组成的数列
    • 注意,和path不一样,这里的数字必须用逗号分割(空格会被忽略)
    • 每一组数字,第一个用来表示填色区域的长度,第二个用来表示非填色区域的长度。

stroke-linecap示例

<?xml version="1.0" standalone="no"?>
<svg width="160" height="140" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <line x1="40" x2="120" y1="20" y2="20" stroke="black" stroke-width="20" stroke-linecap="butt"/>
  <line x1="40" x2="120" y1="60" y2="60" stroke="black" stroke-width="20" stroke-linecap="square"/>
  <line x1="40" x2="120" y1="100" y2="100" stroke="black" stroke-width="20" stroke-linecap="round"/>
</svg>

stroke-linejoin示例

<?xml version="1.0" standalone="no"?>
<svg width="160" height="280" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <polyline points="40 60 80 20 120 60" stroke="black" stroke-width="20"
      stroke-linecap="butt" fill="none" stroke-linejoin="miter"/>
  <polyline points="40 140 80 100 120 140" stroke="black" stroke-width="20"
      stroke-linecap="round" fill="none" stroke-linejoin="round"/>
  <polyline points="40 220 80 180 120 220" stroke="black" stroke-width="20"
      stroke-linecap="square" fill="none" stroke-linejoin="bevel"/>
</svg>

stroke-linedasharray示例

<?xml version="1.0" standalone="no"?>
<svg width="200" height="120" 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,15,5" fill="none"/>
  <path d="M 10 75 L 190 75" stroke="red"
    stroke-linecap="round" stroke-width="1" stroke-dasharray="1,2,3,4,5" fill="none"/>
</svg>

解释说明

  • 第一个例子,该路径首先渲染5个填色单位,10个空白单位,5个填色单位,然后回头以这3个数字做一次循环,但是这次是创建5个空白单位,10个填色单位,5个空白单位。通过这两次循环得到偶数模式,并将这个偶数模式不断重复。
  • 第二个例子,先做5个像素单位的填色,紧接着是5个空白单位,然后又是5个单位的填色。如果你想要更复杂的虚线模式,你可以定义更多的数字

使用CSS

除了定义对象的属性外,你也可以通过CSS来样式化填充和描边。语法和在html里使用CSS一样,只不过你要把background-color、border改成fill和stroke。

注意,不是所有的属性都能用CSS来设置。上色和填充的部分一般是可以用CSS来设置的,比如fill,stroke,stroke-dasharray等,但是不包括下面会提到的渐变和图案等功能。另外,width、height,以及路径的命令等等,都不能用css设置。判断它们能不能用CSS设置还是比较容易的。

SVG规范将属性区分成properties和其他attributes,前者是可以用CSS设置的,后者不能。

3种CSS用法

  1. CSS可以利用style属性插入到元素的行间

    <svg>
    <rect x="10" height="180" y="10" width="180" style="stroke: black; fill: red;"/>
    </svg>
    

  2. 利用<style>设置一段样式段落。就像在<html>里这样的<style>一般放在<head>里,在svg里<style>则放在<defs>标签里。<defs>表示定义,这里面可以定义一些不会在SVG图形中出现、但是可以被其他元素使用的元素。同样可以使用hover

    <?xml version="1.0" standalone="no"?>
    <svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" version="1.1">
      <defs>
        <style type="text/css"><![CDATA[
          #MyRect {
            stroke: black;
            fill: red;
          }
        ]]></style>
      </defs>
      <rect x="10" height="180" y="10" width="180" id="MyRect"/>
    </svg>
    

  3. 你也可以定义一个外部的样式表

    <?xml version="1.0" standalone="no"?>
    <?xml-stylesheet type="text/css" href="style.css"?>
    
    <svg width="200" height="50" xmlns="http://www.w3.org/2000/svg" version="1.1">
      <rect height="10" width="10" id="MyRect2"/>
    </svg>
    

渐变

并非只能简单填充颜色和描边,更令人兴奋的是,你还可以创建和并在填充和描边上应用渐变色。

有两种类型的渐变:线性渐变和径向渐变。你必须给渐变内容指定一个id属性,否则文档内的其他元素就不能引用它。为了让渐变能被重复使用,渐变内容需要定义在<defs>标签内部,而不是定义在形状上面

线性渐变

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

<?xml version="1.0" standalone="no"?>
<svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
      <linearGradient id="Gradient1">
        <stop class="stop1" offset="0%"/>
        <stop class="stop2" offset="50%"/>
        <stop class="stop3" offset="100%"/>
      </linearGradient>
      <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
        <stop offset="0%" stop-color="red"/>
        <stop offset="50%" stop-color="black" stop-opacity="0"/>
        <stop offset="100%" stop-color="blue"/>
      </linearGradient>
      <style type="text/css"><![CDATA[
        #rect1 { fill: url(#Gradient1); }
        .stop1 { stop-color: red; }
        .stop2 { stop-color: black; stop-opacity: 0; }
        .stop3 { stop-color: blue; }
      ]]></style>
  </defs>
  <rect id="rect1" x="10" y="10" rx="15" ry="15" width="100" height="100"/>
  <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)"/>
</svg>

以上是一个应用了线性渐变的<rect>元素的示例。线性渐变内部有几个<stop> 结点,这些结点通过指定位置的offset(偏移)属性和stop-color(颜色中值)属性来说明在渐变的特定位置上应该是什么颜色;可以直接指定这两个属性值,也可以通过CSS来指定他们的值,该例子中混合使用了这两种方法.

使用渐变时,我们需要在一个对象的属性fill或属性stroke中引用它,这跟你在CSS中使用url引用元素的方法一样。在本例中,url只是一个渐变的引用,我们已经给这个渐变一个ID——“Gradient”。要想附加它,将属性fill设置为url(#Gradient)即可。现在对象就变成多色的了,也可以用同样的方式处理stroke。

<linearGradient>元素还需要一些其他的属性值,它们指定了渐变的大小和出现范围。渐变的方向可以通过两个点来控制,它们分别是属性x1、x2、y1和y2,这些属性定义了渐变路线走向。渐变色默认是水平方向的,但是通过修改这些属性,就可以旋转该方向。下例中的Gradient2创建了一个垂直渐变。

注意: 你也可以在渐变上使用xlink:href属性。如果使用了该属性时,一个渐变的属性和颜色中值(stop)可以被另一个渐变包含引用。在下例中,你就不需要再Grandient2中重新创建全部的颜色中值(stop)。

<linearGradient id="Gradient1">
   <stop id="stop1" offset="0%"/>
   <stop id="stop2" offset="50%"/>
   <stop id="stop3" offset="100%"/>
 </linearGradient>
 <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1"
    xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Gradient1"/>

径向渐变

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

stops的使用方法与之前一致,但是现在这个对象的颜色是中间是红色的,且向着边缘的方向渐渐的变成蓝色。跟线性渐变一样,<radialGradient> 节点可以有多个属性来描述其位置和方向,但是它更加复杂。

cx、cy、fx、fy和r的取值范围0-1,也就是宽度和高度的比率,参考gradientUnits

cx,cy表示渐变的中心点,r表示渐变的半径,这三者构成了渐变区域。fx,fy表示渐变区域的焦点。

  • 若无fx,fy属性,则fx,fy和cx,cy重叠
  • 若有fx,fy属性,fx,fy的取值点不能超出渐变区域,否则无法渐变。

示例

<?xml version="1.0" standalone="no"?>
<svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
      <radialGradient id="RadialGradient1">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
      <radialGradient id="RadialGradient2" cx="0.25" cy="0.25" r="0.25">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
  </defs>
  <rect x="10" y="10" rx="15" ry="15" width="100" height="100" fill="url(#RadialGradient1)"/> 
  <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#RadialGradient2)"/> 
</svg>

中心和焦点

<?xml version="1.0" standalone="no"?>
<svg width="120" height="120" version="1.1"
  xmlns="http://www.w3.org/2000/svg">
  <defs>
      <radialGradient id="Gradient"
            cx="0.5" cy="0.5" r="0.5" fx="0.25" fy="0.25">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
  </defs>
  <rect x="10" y="10" rx="15" ry="15" width="100" height="100"
        fill="url(#Gradient)" stroke="black" stroke-width="2"/>
  <circle cx="60" cy="60" r="50" fill="transparent" stroke="white" stroke-width="2"/>
  <circle cx="35" cy="35" r="2" fill="white" stroke="white"/>
  <circle cx="60" cy="60" r="2" fill="white" stroke="white"/>
  <text x="38" y="40" fill="white" font-family="sans-serif" font-size="10pt">(fx,fy)</text>
  <text x="63" y="63" fill="white" font-family="sans-serif" font-size="10pt">(cx,cy)</text>
</svg>
(fx,fy) (cx,cy)

spreadMethod

线性渐变和径向渐变都需要一些额外的属性用于描述渐变过程,这里我希望额外提及一个spreadMethod属性,该属性控制了当渐变到达终点的行为,但是此时该对象尚未被填充颜色.

  • pad 就是我们之前看到的,即当渐变到达终点时,最终的偏移颜色被用于填充对象剩下的空间
  • reflect reflect会让渐变一直持续下去,不过它的效果是与渐变本身是相反的,以100%偏移位置的颜色开始,逐渐偏移到0%位置的颜色,然后再回到100%偏移位置的颜色
  • repeat repeat也会让渐变继续,但是它不会像reflect那样反向渐变,而是跳回到最初的颜色然后继续渐变。
<?xml version="1.0" standalone="no"?>
<svg width="220" height="220" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
      <radialGradient id="GradientPad"
            cx="0.5" cy="0.5" r="0.4" fx="0.75" fy="0.75"
            spreadMethod="pad">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
      <radialGradient id="GradientReflect"
            cx="0.5" cy="0.5" r="0.4" fx="0.75" fy="0.75"
            spreadMethod="reflect">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
      <radialGradient id="GradientRepeat"
            cx="0.5" cy="0.5" r="0.4" fx="0.75" fy="0.75"
            spreadMethod="repeat">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
      <radialGradient id="GradientReflect"
            cx="0.5" cy="0.5" r="0.4" fx="0.75" fy="0.75"
            spreadMethod="reflect">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
  </defs>
  <rect x="10" y="10" rx="15" ry="15" width="100" height="100" fill="url(#GradientPad)"/>
  <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#GradientRepeat)"/>
  <rect x="120" y="120" rx="15" ry="15" width="100" height="100" fill="url(#GradientReflect)"/>
  <text x="15" y="30" fill="white" font-family="sans-serif" font-size="12pt">Pad</text>
  <text x="15" y="140" fill="white" font-family="sans-serif" font-size="12pt">Repeat</text>
  <text x="125" y="140" fill="white" font-family="sans-serif" font-size="12pt">Reflect</text>
</svg>

Pad Reflect Repeat

gradientUnits

该属性有两个值,默认值为objectBoundingBox

  • objectBoundingBox 我们目前看到的效果都是在这种系统下的,它大体上定义了对象的渐变大小范围,所以你只要指定从0到1的坐标值,渐变就会自动的缩放到对象相同大小
  • userSpaceOnUse 使用绝对单元,所以你必须知道对象的位置,并将渐变放在同样地位置上。上例中的radialGradient需要被重写成

图案

在我看来patterns(图案)是SVG中用到的最让人混淆的填充类型之一。它的功能非常强大,所以我认为他们值得讨论一下并且我们应至少对他们有最基本的了解。跟渐变一样,<pattern>需要放在SVG文档的<defs>内部。

<?xml version="1.0" standalone="no"?>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>
    <linearGradient id="Gradient1">
      <stop offset="5%" stop-color="white"/>
      <stop offset="95%" stop-color="blue"/>
    </linearGradient>
    <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
      <stop offset="5%" stop-color="red"/>
      <stop offset="95%" stop-color="orange"/>
    </linearGradient>
    <pattern id="Pattern" x="0" y="0" width=".25" height=".25">
      <rect x="0" y="0" width="50" height="50" fill="skyblue"/>
      <rect x="0" y="0" width="25" height="25" fill="url(#Gradient2)"/>
      <circle cx="25" cy="25" r="20" fill="url(#Gradient1)" fill-opacity="0.5"/>
    </pattern>
  </defs>
  <rect fill="url(#Pattern)" stroke="black" x="0" y="0" width="200" height="200"/>
</svg>

<?xml version="1.0" standalone="no"?>
<svg width="300" height="300" xmlns="http://www.w5.org/2000/svg/" version="1.1">
  <defs>
    <linearGradient id="Gradient111">
      <stop offset="5%" stop-color="white"/>
      <stop offset="95%" stop-color="blue"/>
    </linearGradient>
    <linearGradient id="Gradient222" x1="0" x2="0" y1="0" y2="1">
      <stop offset="5%" stop-color="red"/>
      <stop offset="95%" stop-color="orange"/>
    </linearGradient>
    <pattern id="Pattern12" x="0" y="0" width=".25" height=".25">
      <rect x="0" y="0" width="50" height="50" fill="skyblue"/>
      <rect x="0" y="0" width="25" height="25" fill="url(#Gradient222)"/>
      <circle cx="25" cy="25" r="20" fill="url(#Gradient111)" fill-opacity="0.5"/>
    </pattern>
  </defs>
  <rect fill="url(#Pattern12)" stroke="black" x="0" y="0" width="300" height="300"/>
</svg>

改变对象大小,并不能自适应

patternUnits

  • objectBoundingBox 默认
  • userSpaceOnUse

patternContentUnits

  • userSpaceOnUse 默认
  • objectBoundingBox

这意味着除非你至少指定其中一个属性值(patternContentUnits或patternUnits),否则在pattern中绘制的形状将与pattern元素使用的坐标系不同.

如果对象改变了大小,pattern会自适应其大小,但是对象里面的内容不会自适应。如上图对象rect的大小增大了,内容并没有增大

<?xml version="1.0" standalone="no"?>
<svg width="300" height="300" xmlns="http://www.w6.org/2000/svg/" version="1.1">
  <defs>
    <linearGradient id="Gradient11">
      <stop offset="5%" stop-color="white"/>
      <stop offset="95%" stop-color="blue"/>
    </linearGradient>
    <linearGradient id="Gradient22" x1="0" x2="0" y1="0" y2="1">
      <stop offset="5%" stop-color="red"/>
      <stop offset="95%" stop-color="orange"/>
    </linearGradient>
    <pattern id="Pattern123" width=".25" height=".25" patternContentUnits="objectBoundingBox">
      <rect x="0" y="0" width=".25" height=".25" fill="skyblue"/>
      <rect x="0" y="0" width=".125" height=".125" fill="url(#Gradient22)"/>
      <circle cx=".125" cy=".125" r=".1" fill="url(#Gradient11)" fill-opacity="0.5"/>
    </pattern>
  </defs>
  <rect fill="url(#Pattern123)" stroke="black" x="0" y="0" width="300" height="300"/>
</svg>

设置了patternContentUnits="objectBoundingBox",并改变了取值单位后,就可以自适应了

文本

在一个SVG文档中,元素内部可以放任何的文字。

<?xml version="1.0" standalone="no"?>
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <text x="10" y="10">Hello World!</text>
  <text>
  <tspan font-weight="bold" fill="red">This is bold and red</tspan>
</text>
</svg>

Hello World! This is bold and red

Recent Posts
  • XML简介
  • SVG简单示例
  • 什么是像素
  • 基本图形
    • 矩形 rect
    • 圆形 circle
    • 椭圆 ellipse
    • 折现 polyline
    • 多边形 polygon
    • 路径 path
  • 直线路径
  • 曲线路径
    • 贝塞尔曲线 CSQT
    • 弧形 A
  • Fill和Stroke属性
    • 上色 fill stroke
    • 描边 stroke-line(cap|join|dasharray)
  • 使用CSS
  • 渐变
    • 线性渐变
    • 径向渐变
  • 图案
  • 文本
Copyright © 2018-2019 Shiyong Yin