神奇的SVG

XML的重器

Posted by Lorry on June 20, 2018

文章字数:3497, 阅读全文大约需要:9 分钟

SVG (Scalable Vector Graphics) 是基于XML标记语法去描述二维矢量的标签

Namespaces

对于XML来说,SVG是在一个命名空间里的,所以理解命名空间的概念和如何使用十分重要.

比如,XHTML和SVG都有一个<title>属性,user agent怎么区分两者呢?

XML content会通过声明命名空间(namespace declaration)告诉user agent 这个tag是属于哪个dialect

Declare namespace

<svg xmlns="http://www.w3.org/2000/svg">
<!-- more tags here -->
</svg>

xmlns用于声明命名空间,在此声明之下的所有子标签都属于这个空间内.这里看起来是一个link(URI),但实际上仅仅是一个字符串,使用这个只是”惯例”,因为太常见,所以有时候都会被称为”namespace URI” 而不是”namespace name”

Redeclaring the default namespace

如果所有的子代标签都在一个根标签下.该根标签又定义了一个namespace,那么如何使用别的namespace呢?是的.,重写

<html xmlns="http://www.w3.org/1999/xhtml">
  <body>
    <!-- some XHTML tags here -->
    <svg xmlns="http://www.w3.org/2000/svg" width="300px" height="200px">
      <!-- some SVG tags here -->
    </svg>
    <!-- some XHTML tags here -->
  </body>
</html>

Declaring namespace prefixes

有时我们需要定义一个可以让许多不同袁术复用的属性,独立于被使用元素之外的属性, 最常见的就是通过XLink参数定义的href属性,用于链接外部资源,但是你如何告诉user agent这个属性是属于哪一个XML呢?

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <script xlink:href="cool-script.js" type="text/ecmascript"/>
</svg>

上例将 xlink 绑定在了 namespace 为 “http://www.w3.org/2000/svg” 上,然后子元素就可以使用xlink作为命名空间的前缀,让user agent可以知道这个是属于哪个xml的.可以供所有的标签使用(<a> <img> <use>).注意,一定要绑定在namespace上,不然使用xlink会报错,建议始终绑定xlink在命名空间上.

除此之外还可以将前缀绑定到标签名上,

<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:svg="http://www.w3.org/2000/svg">
  <body>
    <h1>SVG embedded inline in XHTML</h1>
    <svg:svg width="300px" height="200px">
      <svg:circle cx="150" cy="100" r="50" fill="#ff0000"/>
    </svg:svg>
  </body>
</html>

svg:svg , svg:circle都是在”http://www.w3.org/2000/svg”命名空间下,注意,重载会将本身及其子元素全部包含在新的namespace中,前缀只会对当前标签起作用.

Scripting in namespaced XML

DOM1 出生的时候还没有namespace这么一个东西,所以会造成在写得代码不认识XML的命名空间,例如svg.为了解决这个问题,出了一个DOM2.本质相同,但是支持SVG

DOM1 (don’t use) DOM2 (use these instead!)
createAttribute createAttributeNS
createElement createElementNS
getAttributeNode getAttributeNodeNS
getAttribute getAttributeNS
getElementsByTagName getElementsByTagNameNS (also added to Element)
getNamedItem getNamedItemNS
hasAttribute hasAttributeNS
removeAttribute removeAttributeNS
removeNamedItem removeNamedItemNS
setAttribute setAttributeNS
setAttributeNode setAttributeNodeNS
setNamedItem setNamedItemNS
var SVG_NS = 'http://www.w3.org/2000/svg';
var XLink_NS = 'http://www.w3.org/1999/xlink';
var image = document.createElementNS(SVG_NS, 'image'); // 创建一个具有命名空间的标签
image.setAttributeNS(null, 'width', '100'); // 如果是DOM1的属性设置时因为没有命名空间的概念,所以设置为null
image.setAttributeNS(null, 'height', '100');
image.setAttributeNS(XLink_NS, 'xlink:href', 'flower.png'); // 设置有命名空间的属性
image.getAttributeNS(null,'width'); // 获取没有命名空间的属性
image.getAttributeNS(null,'height');
image.getAttributeNS(XLink_NS,'xlink:href');// 获取有命名空间的属性

设置一个模板

<svg version="1.1"
     baseProfile="full"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     xmlns:ev="http://www.w3.org/2001/xml-events">
</svg>

或许现在用不到命名空间,但,万一之后需要使用,这回会避免出现很多让你烦恼的问题.

SVG 有意思的东西

<animate> <path>

See the Pen Example by Jiang Lirui (@JiangLiruii) on CodePen.

path

可以使用Illustrator来图形化生成path.

viewbox的放大