SVG笔记

SVG 基础知识

SVG基本图形和属性

图形

  • 矩形
  • 圆形
  • 椭圆
  • 线
  • 折线
  • 多边形

rect.svg

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg">

<rect x="20" y="20" rx="20" ry="20" width="250" height="250" 
style="fill:blue;stroke:pink;stroke-width:5;
fill-opacity:0.1;stroke-opacity:0.9"/>
</svg>

polyline.svg

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg">

<polyline points="0,0 0,20 20,20 20,40 40,40 40,60"
style="fill:white;stroke:red;stroke-width:2"/>

</svg>

polygon.svg

<11770820@qq.com

<tech_support@chinapay.com>, “huang.haisong@chinapay.com“ <huang.haisong@chinapay.com>

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg">

<polygon points="220,100 300,210 170,250"
style="fill:#cccccc;
stroke:#000000;stroke-width:1"/>

</svg>

基本属性

  • fill
  • stroke
  • stroke-width
  • transform

基本操作

API

  • 创建图形 createElementNs(ns,tagName)
var text = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var NS = 'http://www.w3.org/2000/svg';
var tspan = document.createElementNS(NS,'tspan');
  • 添加图形 element.appendChild(childElement) 
  • 设置/获取属性 element.setAttribute(name, value ) / elememt.getAttribute(name)
  • 设置  xlink:href  属性  textPath.setAttributeNS(“http://www.w3.org/1999/xlink",'xlink:href',path)

HTML

<html>
  <head></head>
  <body>
    <img src="sample.svg">                 >
    <embed src="sample.svg"></embed>       > 外部引用式
    <iframe src="sample.svg"></iframe>     >
    <object data="sample.svg"></object>    >
    <svg data-src="img/buble.svg"/>
  </body>
</html>

容器

https://developer.mozilla.org/en-US/docs/Web/SVG/Element/a

<a>, <defs>, <g>, <marker>, 

<mask>, <missing-glyph>, <pattern>, 

<svg>, <switch>, <symbol>

Descriptive elements

<desc>, medadata, title

看medata案例就可以,

SVG 滤镜

Gaussian_blur.svg

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg">

<defs>
<filter id="Gaussian_Blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>

<ellipse cx="200" cy="150" rx="70" ry="40"
style="fill:#ff0000;stroke:#000000;
stroke-width:2;filter:url(#Gaussian_Blur)"/>

</svg>

注解:

  • filter 定义滤镜
  • filter:url引用滤镜
  • stdDeviation 模糊程度
  • in=”SourceGraphic” 定义整个创建效果

滤镜效果有

  • feBlend
  • feColorMatrix
  • feComponentTransfer
  • feComposite
  • feConvolveMatrix
  • feDiffuseLighting
  • feDisplacementMap
  • feFlood
  • feGaussianBlur
  • feImage
  • feMerge
  • feMorphology
  • feOffset
  • feSpecularLighting
  • feTile
  • feTurbulence
  • feDistantLight
  • fePointLight
  • feSpotLight

SVG 滤镜效果可以叠加使用

multi-filter.svg

<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feGaussianBlur -->

<svg width="120" height="120"
 xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink">

  <filter id="dropShadow">
    <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
    <feOffset dx="2" dy="4" />
    <feMerge>
        <feMergeNode />
        <feMergeNode in="SourceGraphic" />
    </feMerge>
  </filter>

  <circle cx="60"  cy="60" r="50" fill="green"
          filter="url(#dropShadow)" />
</svg>

SVG中的坐标系统

2.1 世界,视野和视窗的概念

  • 世界是⽆无穷⼤大的,SVG画布可以是无穷大的
  • 视野是观察世界的⼀一个矩形区域,可以有viewbox定义视野区域
  • 视窗是浏览器开辟的一个区域, width, height - 控制视窗
  • preserveAspectRatio 控制视野和视窗之间关系
<svg xmlns="http://www.w3.org/2000/svg"  width="100" height="100"
     viewBox="0 0 400 300" preserveAspectRatio="xMidYMid meet">
</svg>

动态效果请参照:viewbox.html

2.2 图形分组

  1. 标签来创建分组
  2. 子元素可以继承组属性
  3. transform  属性定义坐标变换
  4. 可以嵌套使用
<svg xmlns="http://www.w3.org/2000/svg"  >
  <g stroke="green" fill="none" transform(0,50)>
    <rect x="100" y="50" width="100" height="50"></rect>
    <rect x="140" y="100" width="20" height="120"></rect>
  </g>
</svg>

注解:

  1. g设置的stroke,fill属性, 两个rect都能继承
  2. transform能整体改变 内坐标

2.3 坐标系统概述

如上图:svg使用的是笛卡尔坐标系统

2.4 四个坐标系

  1. 用户坐标系(User  Coordinate): -> 世界的坐标系
  2. 自身坐标系(Current  Coordinate) -> 每个图形元素或分组独立与生俱来
  3. 前驱坐标系(Previous  Coordinate) -> 父容器的坐标系 
  4. 参考坐标系(Reference  Coordinate) -> 使用其它坐标系来考究自身的情况时使用

2.5 坐标变换

查看ransform.html

  • 嵌套 , 子会继承父g坐标属性

颜色渐变和笔刷

颜色

HSL

渐变

线性渐变

linearGradient.svg

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg">

<defs>
<linearGradient id="orange_red" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(255,255,0);
stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255,0,0);
stop-opacity:1"/>
</linearGradient>
</defs>

<ellipse cx="200" cy="190" rx="85" ry="55"
style="fill:url(#orange_red)"/>

</svg>
  • gradientUnits=”userSpaceOnUse(用的是世界坐标系不是图形当前的坐标系)/objectBoundingBox(默认值)”
  • x1="0%" y1="0%图形最上段, x2="100%" y2="0%图形最下段

放射性渐变

radialGradient.svg

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg">

<defs>
<radialGradient id="grey_blue" cx="50%" cy="50%" r="50%"
fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(200,200,200);
stop-opacity:0"/>
<stop offset="100%" style="stop-color:rgb(0,0,255);
stop-opacity:1"/>
</radialGradient>
</defs>

<ellipse cx="230" cy="200" rx="110" ry="100"
style="fill:url(#grey_blue)"/>

</svg>

注解:

  • cx、cy 和 r 属性定义外圈
  • fx 和 fy 定义内圈,颜色渐变中心点,能产生聚光灯的效果

笔刷 pattern

pattern.svg

<svg xmlns="http://www.w3.org/2000/svg">
    <defs>
        <pattern id="p1" x="0" y="0" width="50" height="50" patternUnits="userSpaceOnUse">
            <circle cx="10" cy="10" r="5" fill="red"></circle>
            <polygon points="30 10 60 50 0 50" fill="green"></polygon>
        </pattern>
           <pattern id="p2" x="0" y="0" width="50" height="50">
            <circle cx="10" cy="10" r="5" fill="red"></circle>
            <polygon points="30 10 60 50 0 50" fill="green"></polygon>
        </pattern>
    </defs>
    <rect x="100" y="100" width="800" height="600" fill="url(#p1)" stroke="blue"></rect>
    <rect x="100" y="100" width="800" height="600" fill="url(#p2)" stroke="blue"></rect>
</svg>
  • objectBoundingBox : (默认)为容器百分比
  • userSpaceOnUse : width 和 height 以世界坐标系为准,为宽度、高度
  • patternUnits/patternUnitsContent

Path 高级

概述

  • 规范:http://www.w3.org/TR/SVG11/paths.html 

  • path.svg 黑色山角型

      <?xml version="1.0" standalone="no"?>
      <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
      "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    
      <svg width="100%" height="100%" version="1.1"
      xmlns="http://www.w3.org/2000/svg">
      <path d="M250 150 L150 350 L350 350 Z" />
      </svg>

Path-命令汇总

  • M = moveto
  • L = lineto
  • H = horizontal lineto
  • V = vertical lineto
  • C (x1,y1,x2,y2,x,y)+ = curveto 从当前位置绘制三次⻉贝塞尔曲线到指定位置
  • S = smooth curveto 从当前位置光滑绘制三次⻉贝塞尔曲线到指定位置
  • Q = quadratic Belzier curve 绘制⼆二次⻉贝塞尔曲线
  • T = smooth quadratic Belzier curveto 光滑绘制⼆二次⻉贝塞尔曲线
  • A (rx,ry,xr,laf,sf,x,y) = elliptical Arc
  • Z = closepath

A (rx,ry,xr,laf,sf,x,y) -  绘制弧线 

  • xr  -  (xAxis-rotation) 弧线所在椭圆的长轴角度 
  • laf  -  (large-arc-flag) 是否选择大弧长
  • sf  -  (sweep-flag) 是否选择逆的那一段时针方向

基本规律

  • 大写为绝对位置命令,小写为相对位置命令

参考资料

SVG 文本

.svg

<svg viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg">
  <style>
    .small { font: italic 13px sans-serif; }
    .heavy { font: bold 30px sans-serif; }

    /* Note that the color of the text is set with the    *
     * fill property, the color property is for HTML only */
    .Rrrrr { font: italic 40px serif; fill: red; }
  </style>

  <text x="20" y="35" class="small">My</text>
  <text x="40" y="35" class="heavy">cat</text>
  <text x="55" y="55" class="small">is</text>
  <text x="65" y="55" class="Rrrrr">Grumpy!</text>
</svg>

textPath.svg

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">

  <!-- to hide the path, it is usually wrapped in a <defs> element -->
  <!-- <defs> -->
  <path id="MyPath" fill="none" stroke="red"
        d="M10,90 Q90,90 90,45 Q90,10 50,10 Q10,10 10,40 Q10,70 45,70 Q70,70 75,50" />
  <!-- </defs> -->

  <text>
    <textPath href="#MyPath">
      Quick brown fox jumps over the lazy dog.
    </textPath>
  </text>

</svg>
  • x/dx/startOffset 都能使文字在path描绘的路径向前移动
  • text-anchor=”middle”, 一段文字初始化锚点在一段文字中间

dy dx 应用案例

JS脚本控制

  • setAttributeNS()设置xlink:href 属性
    textPath.setAttributeNS("http://www.w3.org/1999/xlink",'xlink:href',path)

实战案例查看 path.html 或者是 附录-经典案例-正玄字体

tspan.svg

<svg xmlns="http://www.w3.org/2000/svg" >
  <defs>
    <pattern id="grid" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
      <path stroke="#f0f0f0" fill="none" d="M0,0H20V20"></path>
    </pattern>
  </defs>
  <rect width="1200" height="1000" fill="url(#grid)"></rect>
  <text id="sintext" x="100" y="100" style="font-size: 50px; font-family: 'Arial'; ">
    <tspan fill="red" dy="-20 20">AB</tspan>
    <tspan stroke="green" fill="none" stroke-width="2" dy="-40 40">CDE</tspan>
    <!--简单叠加的效果-->
    <tspan fill="blue" dy="20 20 20 20 20 20">FGHIJKLM</tspan>
  </text>
  <path d="M100,0V200M0,100H200" stroke="red" />
</svg>

垂直居中问题

字体位置各种案例展示

代码如下

Example.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <select id="ta">
    <option value="start">start</option>
    <option value="end">end</option>
    <option value="middle">center</option>
  </select>
  <select id="select"></select>
  <svg>
    <path stroke="green" d="M 0 100.5 500 100.5 M 140 0 v 200"/>
    <text id="text" x="140" y="100" fill="red" font-size="50">慕课网</text>
    <rect id="rect" stroke="blue" fill="none"></rect>
  </svg>
</body>
</html>

Example.js

var values = "auto | use-script | no-change | reset-size | ideographic | alphabetic | hanging | mathematical | central | middle | text-after-edge | text-before-edge | text-top | text-bottom".split(' | ');

values.forEach(function(value) {
  var opt = document.createElement('option');
  opt.value = opt.textContent = value;
  select.appendChild(opt);
});

select.addEventListener('input', function() {
  text.setAttribute('dominant-baseline', select.value);
  var box = text.getBBox();
  rect.setAttribute('x', box.x);
  rect.setAttribute('y', box.y);
  rect.setAttribute('width', box.width);
  rect.setAttribute('height', box.height);
});

ta.addEventListener('input', function() {
  text.setAttribute('text-anchor', ta.value);
});

案例2:自定义top,center,bottom对齐方式

https://jsbin.com/vezegib/edit?html,js,console

图形引用、裁切和蒙版

<use> 
   xlink:href = "#id" 
<clipPath> 
  clip-path = "url(#clip-id)" 
<mask>
  mask="url(#mask-id)"

starsky

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>星空</title>
</head>
<style>
  html, body {
    margin: 0;
    height: 100%;
    width: 100%;
    padding: 0;
    background: #001122;
    line-height: 0;
    font-size: 0;
  }
</style>
<body>
<svg width="100%" height="100%"
     viewBox="-400 -300 800 600"
     preserveAspectRatio="xMidYMid slice">
  <defs>
    <polygon id="star" points="0 -10 2 -2 10 0 2 2 0 10 -2 2 -10 0 -2 -2" fill="white"></polygon>
  </defs>
  <g id="real" >
    <g id="start-group"/>
    <g id="moon-group">
      <mask id="moon-mask">
        <circle r="70" cx="-250" cy="-120" fill="white"></circle>
        <circle r="70" cx="-220" cy="-200" fill="black"></circle>
      </mask>
      <circle r="70" cx="-250" cy="-120" fill="white" mask="url(#moon-mask)"></circle>

    </g>
    <g id="light-tower " transform="translate(250,0)">
      <defs>
        <linearGradient id="tower" x1="0" y1="0" x2="1" y2="1">
          <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,.8"></stop>
          <stop offset="1" stop-color="rgba(255,255,255,0"></stop>
        </radialGradient>

        <clipPath id="light-clip">
          <polygon points="0 0 -400 -15 -400 15">
            <animateTransform
              attributeName="transform"
              attributeType="XML"
              type="rotate"
              from="0"
              to="360"
              dur="10s"
              repeatCount="indefinite"/>
          </polygon>
          <circle cx="0" cy="0" r="2"/>
        </clipPath>
      </defs>
      <polygon points="0 0 5 50 -5 50" fill="url(#tower)"></polygon>
      <ellipse rx="300" ry="100" cx="0" cy="0" fill="url(#light)" clip-path="url(#light-clip)"></ellipse>
    </g>
  </g>
  <g id="reflect" transform="translate(0,50)" mask="url(#fading)">
      <defs>
        <linearGradient id="fade" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="rgba(255,255,255,.3)"/>
          <stop offset="0.5" stop-color="rgba(255,255,255,0)"/>
        </linearGradient>
        <mask id="fading">
          <rect x="-400" y="0" width="800" height="300" fill="url(#fade)"></rect>
        </mask>
      </defs>
    <!--use 是不能使用mask的-->
    <use xlink:href="#real" transform="scale(1,-1) translate(0,-50)" ></use>

  </g>
  <line x1="-400" y1="50" x2="400" y2="50" stroke="white"/>
</svg>
</body>
<script>
  var NS = 'http://www.w3.org/2000/svg'
  var XLINK_NS = 'http://www.w3.org/1999/xlink';
  var page = document.querySelector('svg');

  function use(origin) {
    var _use = document.createElementNS(NS, 'use');
    _use.setAttributeNS(XLINK_NS, 'xlink:href', '#' + origin.id);
    return _use;
  }

  function random(min, max) {
    return min + (max - min) * Math.random();
  }

  renderStar();

  function renderStar() {
    var starRef = document.getElementById('star');
    var starGroup = document.getElementById('start-group');
    var starCount = 500;

    var star;
    while (starCount--) {
      star = use(starRef);
      star.setAttribute('opacity', random(0.1, 0.4));
      star.setAttribute('transform', 'translate(' + random(-400, 400) + ',' + random(-300, 50) + ')' +
        'scale(' + random(0.1, 0.8) + ')'
      );
      starGroup.appendChild(star);
    }
  }
</script>
</html>

SVG动画

参考资料

动画标签概述

animate.svg

<?xml version="1.0"?>
<svg width="120" height="120" viewBox="0 0 120 120" version="1.1"
     xmlns="http://www.w3.org/2000/svg">

  <rect x="10" y="10" width="100" height="100">
    <animate attributeType="XML" attributeName="x" from="-100" to="120"
        dur="10s" repeatCount="indefinite"/>
  </rect>
</svg>

motion.xml

<?xml version="1.0"?>
<svg width="120" height="120" viewBox="0 0 120 120"
    xmlns="http://www.w3.org/2000/svg" version="1.1"
    xmlns:xlink="http://www.w3.org/1999/xlink">

  <!-- Draw the outline of the motion path in grey, along
       with 2 small circles at key points -->
  <path d="M10,110 A120,120 -45 0,1 110 10 A120,120 -45 0,1 10,110"
      stroke="lightgrey" stroke-width="2" 
      fill="none" id="theMotionPath"/>
  <circle cx="10" cy="110" r="3" fill="lightgrey"  />
  <circle cx="110" cy="10" r="3" fill="lightgrey"  />

  <!-- Red circle which will be moved along the motion path. -->
  <circle cx="" cy="" r="5" fill="red">

    <!-- Define the motion path animation -->
    <animateMotion dur="6s" repeatCount="indefinite">
      <mpath xlink:href="#theMotionPath"/>
    </animateMotion>
  </circle>
</svg>
  • <mpath xlink:href="#theMotionPath"/> 引用上面的路径定义

path 可以在animation内部

sample2.html

<!DOCTYPE html>
<html lang="en">
<style>
  html,body, svg{
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
  }
</style>
<head>
    <meta charset="UTF-8">
    <title>SVG 动画</title>
</head>
<body>
  <svg viewBox="-400 -400 800 800" xmlns="http://www.w3.org/2000/svg" version="1.1"
       xmlns:xlink="http://www.w3.org/1999/xlink">
    <rect x="-25" y="-25" height="50" width="50" fill="rgba(0,255,255,0.6)">
      <animateMotion
        path="M 0 0L 100 100A 200 200 0 1 0 0 -100"
        dur="3s"
        repeatCount="indefinite"
        rotate="auto">
        <!--<mpath xlink:href="#motion-path"/>-->
      </animateMotion>
    </rect>
    <path id="motion-path" d="M 0 0L 100 100A 200 200 0 1 0 0 -100" stroke="gray" fill="none"/>
  </svg>
</body>
</html>

animateTransform

transform.svg

<svg width="120" height="120" viewBox="0 0 120 120"
     xmlns="http://www.w3.org/2000/svg">

    <polygon points="60,30 90,90 30,90">
        <animateTransform attributeName="transform"
                          attributeType="XML"
                          type="rotate"
                          from="0 60 70"
                          to="360 60 70"
                          dur="10s"
                          repeatCount="indefinite"/>
    </polygon>
</svg>

参数设置

实战案例

动画顺序

<svg viewBox="-400 -400 800 800" xmlns="http://www.w3.org/2000/svg" version="1.1"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <rect x="-25" y="-25" height="80" width="80" fill="rgba(0,255,255,0.6)">
    <animate id="first"
             attributeName="x"
             attributeType="XML"
             from="100"
             to="500"
             dur="1s"
             fill="freeze"
             begin="0;second.end"
    />
    <animate id="second"
             attributeName="x"
             attributeType="XML"
             from="500"
             to="100"
             dur="1s"
             fill="freeze"
             begin="first.end"
    />
    <animate id="third"
             attributeName="fill"
             attributeType="XML"
             from="red"
             to="yellow"
             dur="6s"
             fill="freeze"
    />

SVG 工具

svgo

SVG 优化工具,删减多余的内容,减少SVG大小

网页工具svgomg

SVG动画编辑工具

附录

安卓相关文章

官方文档

学习资料

经典案例

metadata.svg

<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/metadata -->

<svg width="400" viewBox="0 0 400 300"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <metadata>
    <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
             xmlns:connect="http://www.w3.org/1999/08/29-svg-connections-in-RDF#">
      <rdf:Description about="#CableA">
        <connect:ends rdf:resource="#socket1"/>
        <connect:ends rdf:resource="#ComputerA"/>
      </rdf:Description>
      <rdf:Description about="#CableB">
        <connect:ends rdf:resource="#socket2"/>
        <connect:ends rdf:resource="#ComputerB"/>
      </rdf:Description>
      <rdf:Description about="#CableN">
        <connect:ends rdf:resource="#socket5"/>
        <connect:ends>Everything</connect:ends>
      </rdf:Description>
      <rdf:Description about="#Hub">
        <connect:ends rdf:resource="#socket1"/>
        <connect:ends rdf:resource="#socket2"/>
        <connect:ends rdf:resource="#socket3"/>
        <connect:ends rdf:resource="#socket4"/>
        <connect:ends rdf:resource="#socket5"/>
      </rdf:Description>
    </rdf:RDF>
  </metadata>
  <title>Network</title>
  <desc>An example of a computer network based on a hub.</desc>

  <style>
    svg {
      /* Default styles to be inherited */
      fill: white;
      stroke: black;
    }
    text { fill: black; stroke: none; }
    path { fill: none; }
  </style>

  <!-- Define symbols used in the SVG -->
  <defs>

    <!-- hubPlug symbol. Used by hub symbol -->
    <symbol id="hubPlug">
      <desc>A 10BaseT/100baseTX socket</desc>
      <path d="M0,10 h5 v-9 h12 v9 h5 v16 h-22 z"/>
    </symbol>

    <!-- hub symbol -->
    <symbol id="hub">
      <desc>A typical 10BaseT/100BaseTX network hub</desc>
      <text x="0" y="15">Hub</text>
      <g transform="translate(0 20)">
        <rect width="253" height="84"/>
        <rect width="229" height="44" x="12" y="10"/>
        <circle fill="red" cx="227" cy="71" r="7" />
        <!-- five groups each using the defined socket -->
        <g id="sock1et" transform="translate(25 20)">
          <title>Socket 1</title>
          <use xlink:href="#hubPlug"/>
        </g>
        <g id="socket2" transform="translate(70 20)">
          <title>Socket 2</title>
          <use xlink:href="#hubPlug"/>
        </g>
        <g id="socket3" transform="translate(115 20)">
          <title>Socket 3</title>
          <use xlink:href="#hubPlug"/>
        </g>
        <g id="socket4" transform="translate(160 20)">
          <title>Socket 4</title>
          <use xlink:href="#hubPlug"/>
        </g>
        <g id="socket5" transform="translate(205 20)">
          <title>Socket 5</title>
          <use xlink:href="#hubPlug"/>
        </g>
      </g>
    </symbol>

    <!-- computer symbol -->
    <symbol id="computer">
      <desc>A common desktop PC</desc>
      <g id="monitorStand" transform="translate(40 121)">
        <title>Monitor stand</title>
        <desc>One of those cool swivelling monitor stands that sit under the monitor</desc>
        <path d="m0,0 S 10 10 40 12"/>
        <path d="m80,0 S 70 10 40 12"/>
        <path d="m0,20 L 10 10 S 40 12 70 10 L 80 20z"/>
      </g>
      <g id="monitor">
        <title>Monitor</title>
        <desc>A very fancy monitor</desc>
        <rect width="160" height="120"/>
        <rect fill="lightgrey" width="138" height="95" x="11" y="12"/>
      </g>
      <g id="processor" transform="translate(0 142)">
        <title>The computer</title>
        <desc>A desktop computer - broad flat box style</desc>
        <rect width="160" height="60"/>
        <g id="discDrive" transform="translate(70 8)">
          <title>disc drive</title>
          <desc>A built-in disc drive</desc>
          <rect width="58" height="3" x="12" y="8"/>
          <rect width="8" height="2" x="12" y="15"/>
        </g>
        <circle cx="135" cy="40" r="5"/>
      </g>
     </symbol>
  </defs>

  <text x="0" y="15">Network</text>

  <!-- Use the hub symbol. -->
  <g id="Hub" transform="translate(80 45)">
    <title>Hub</title>
    <use xlink:href="#hub" transform="scale(0.75)"/>
  </g>

  <!-- Use the computer symbol. -->
  <g id="ComputerA" transform="translate(20 170)">
    <title>Computer A</title>
    <use xlink:href="#computer" transform="scale(0.5)"/>
  </g>

  <!-- Use the same computer symbol. -->
  <g id="ComputerB" transform="translate(300 170)">
    <title>Computer B</title>
    <use xlink:href="#computer" transform="scale(0.5)"/>
  </g>

  <!-- Draw Cable A. -->
  <g id="CableA" transform="translate(107 88)">
    <title>Cable A</title>
    <desc>10BaseT twisted pair cable</desc>
    <path d="M0,0c100,140 50,140 -8,160"/>
  </g>

  <!-- Draw Cable B. -->
  <g id="CableB" transform="translate(142 88)">
    <title>Cable B</title>
    <desc>10BaseT twisted pair cable</desc>
    <path d="M0,0c100,180 110,160 159,160"/>
  </g>

  <!-- Draw Cable N. -->
  <g id="CableN" transform="translate(242 88)">
     <title>Cable N</title>
     <desc>10BaseT twisted pair cable</desc>
     <path d="M0,0c0,-70 20,-50 60,-50"/>
  </g>
</svg>

正玄字体

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>正玄字体</title>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" x="0" y="0" width="100%" height="100%">
  <defs>
    <pattern id="grid" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
      <path stroke="#f0f0f0" fill="none" d="M0,0H20V20"></path>
    </pattern>
  </defs>
  <rect width="4200" height="2000" fill="url(#grid)"></rect>
  <text id="sintext" x="100" y="160" style="font-size: 14px; font-family: 'Arial'; ">ABCDEFGHIJKLMNOPQRSTUVWXYZ</text>
  <path d="M100,0V200M0,100H200" stroke="red" transform="translate(0,60)"/>
  <text id="sintext2" x="100" y="360" style="font-size: 14px; font-family: 'Arial'; "></text>
</svg>
<style>
  body {
    width: 100vm;
    height: 100vm;
  }

  svg {
    overflow: visible;
  }
</style>
<script>
  var n = 26;
  var x = [];
  var y = null;
  var i = n;
  var s = 100;
  var w = 0.02;
  var t = 0;



  var text = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  var NS = 'http://www.w3.org/2000/svg';

  while (i--) {
    x.push(10);
    var tspan = document.createElementNS(NS,'tspan');
    tspan.textContent = text[n -i -1];
    sintext2.appendChild(tspan);
    var h = Math.round(360 / 26 * i);
    tspan.setAttribute('fill','hsl(' + h + ',100%,80%')
  }

  function arrange(t) {
    y = [];
    var ly = 0, cy;
    for (i = 0; i < n; i++) {
      cy = -s * Math.sin(w * i * 20 + t);
      y.push(cy - ly);
      ly = cy;
    }
    console.table(y);
  }

  function render() {
    sintext.setAttribute('dx', x.join(' '));
    sintext.setAttribute('dy', y.join(' '));
    sintext2.setAttribute('dx', x.join(' '));
    sintext2.setAttribute('dy', y.join(' '));
  }

  function frame() {
    t += 0.02;
    arrange(t);
    render();
    requestAnimationFrame(frame)
  }

  frame()
</script>
</body>
</html>