SVG编程告诫

翻译了一篇关于SVG编程注意事项的文章, 对比以前的代码,发现犯了很多错误,只能在以后的代码中注意了。现在贴出来,希望对使用SVG的朋友有所帮助。中英文对照,以便存在翻译错误时修改。

 

There are a lot of mistakes in the SVG documents currently found on the Web. Because Adobe's SVG Viewer ignores many of these errors, the maintainers of these documents usually don't realise when they're doing something wrong. Unfortunately, the result is that far too often SVG on the Web doesn't work in Mozilla, Batik or one of the other SVG implementations. It is important that these problems are addressed as soon as possible to prevent them from propagating into authoring tools and the SVG documents that people will write in the future.
现在在网上可以看到很多存在缺陷的 SVG 文档。因为 Adobe SVG Viewer 忽略了很多这样的错误,文档维护人员通常没有意识到它们的存在。不幸的是,这些错误很可能导致文档在其它 SVG 实现中,例如 Mozilla, Batik 等,不能正常工作。目前重要的是尽快澄清这些错误,让相关人员以后在创作 SVG 发布工具和文档时,能够避免重复这些错误。
This document highlights some of the most common mistakes made in SVG content, and explains what SVG maintainers can do to fix them. The hope is that the SVG community will read this document, and that individual members of the community will do what they can to make sure that SVG on the Web is as portable as possible. Please spread the word. If you see others making any of the mistakes described here, please let them know so that they can correct them. Even more important, if you know of SVG authoring tools that make these mistakes please contact the vendor and let me know . Feel free to link to this document, and please send me your feedback. My email address is jwatt@jwatt.org.
本文指出 SVG 中一些最常见的错误,并且指导 SVG 文档维护人员如何解决这些问题。希望 SVG 社区能够了解本文的内容,而且社区成员能够尽其所能,确保网上的 SVG 文档尽可能的具有移植性。请宣传这些内容。如果你看到其它人正在犯本文中描述的错误,请指出以便他们修改。更重要的是,如果你知道某些 SVG 发布工具存在这些问题,请通知供应商并通知笔者本人。本文可以自由链接,欢迎你的回复。笔者的邮件地址是 jwatt@jwatt.org.
Contents
·                               Configure your server for SVG
·                               Don't include a DOCTYPE declaration
·                               Bind the required namespaces
·                               Avoid the 'style' attribute where possible
·                               Specify units when assigning lengths to properties
·                               Use namespace aware DOM methods
·                               Don't use Adobe's getter and setter extensions
内容
·                               SVG 配置你的服务器
·                               不要包含 DOCTYPE 声明
·                               绑定必要的名字空间
·                               尽可能避免使用 style 属性
·                               为属性值分配长度时指定单位
·                               使用名字空间敏感的 DOM 方法
·                               不要使用 Adobe getter setter 扩展
Configure your server for SVG
This isn't really an issue with SVG content itself, but nevertheless, server misconfiguration is a very common reason for SVG failing to load. For security and correctness reasons, some browsers decides how to handle files by looking at the HTTP headers the server sends with them. If your server isn't configured to send the correct headers with the SVG files it serves, then a browser like Mozilla won't treat those files as SVG. Instead it will most likely show the markup of the files as text or encoded garbage, or even ask the viewer to choose an application to open them. For normal SVG files, servers should send the HTTP header:
Content-Type: image/svg+xml
For gzipped SVG files, servers should send the HTTP headers:
Content-Type: image/svg+xml
Content-Encoding: gzip
You can check that your server is sending the correct HTTP headers with your SVG files by using a site such as web-sniffer.net. Submit the URL of one of your SVG files and look at the HTTP response headers. If you find that your server is not sending the headers with the values given above, then you should contact your Web host. If you have problems convincing them to correctly configure their servers for SVG, there may be ways to do it yourself. See the server configuration page on the SVG wiki for a range of simple solutions.
SVG 配置你的服务器
这个问题不是 SVG 内容本身的问题,但是,服务器的错误配置是导致 SVG 加载失败的一个非常常见的原因。为了确保内容的安全和正确,一些浏览器根据服务器发送的 HTTP 头决定文件的处理方式。如果你的服务器没有为 SVG 发送正确的头信息,象 Mozilla 之类的浏览器不会将内容当作 SVG 处理,在大多数情况下浏览器将标记文件显示为文本或乱码,甚至请求用户选择一个应用程序以打开文件。对于一般的 SVG 文件,服务器应当发送以下 HTTP 头信息:
Content-Type: image/svg+xml
GZIP 压缩的 SVG 文件,应当发送
Content-Type: image/svg+xmlContent-Encoding: gzip
你可以通过一个网站,例如 web-sniffer.net ,来检查你的服务器是否为 SVG 发送了正确的 HTTP 头信息。通过向网站提交一个 SVG 文件的 URL 地址,可以得到并检查返回的 HTTP 头信息。如果发现服务器没有返回上述的正确信息,请联系你的站点提供者,如果不能说服他们为 SVG 正确的配置服务器,你可能需要自行解决这个问题。在 SVG 维基( wiki )中的服务器配置页面里可以找到一系列简单的解决办法。
 
Don't include a DOCTYPE declaration
XML Document Type Definitions, or DTDs for short, are a feature of XML used to validate the contents of a document. A DTD is associated with a document by placing a DOCTYPE declaration in the document. The following line is an example of an SVG DOCTYPE declaration.
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
Unfortunately the SVG DTDs are a source of so many issues that the SVG WG has decided not to write one for the upcoming SVG 1.2 standard. In fact SVG WG members are even telling people not to use a DOCTYPE declaration in SVG 1.0 and 1.1 documents. Instead always include the 'version' and 'baseProfile' attributes on the root <svg> tag, and assign them appropriate values as in the following example.
<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">
If for some reason you want to use the inline features of DOCTYPE declarations (to create entities, etc.), simply omit the public and system identifiers. Your DOCTYPE declaration should then look like this.
<!DOCTYPE svg [
 <!-- entities etc. here -->
]>
不要包含 DOCTYPE 声明
XML 文档类型定义,简称为 DTD ,用来验证 XML 文档内容的有效性。在文档中使用 DOCTYPE 声明用于关联文档和 DTD 定义。下面是一个 SVG DOCTYPE 声明的例子。
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
不幸的是 SVG DTD 是很多问题的根源,因此 SVG WG 决定在将来的 SVG1.2 标准中不使用 DTD 。实际上 SVG WG 成员甚至建议人们在 SVG1.0 SVG1.1 中也不使用 DOCTYPE 。作为替代的是,应当总在 SVG 根元素中包含 'version' 'baseProfile' 属性,并设置相应的属性值,例如:
<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">
出于某些原因,如果希望使用 DOCTYPE 声明的内联特性(例如创建实体等),以避免公有和系统标识时, DOCTYPE 声明应当如下使用:
<!DOCTYPE svg [
 <!-- entities etc. here -->
]>
Bind the required namespaces
SVG is a namespaced XML dialect, and as a consequence all the XML dialects used in your SVG documents must be bound to their namespace as specified in the Namespaces in XML recommendation. It is sensible to bind the SVG and XLink namespaces at a minimum, and possibly also the XML Events namespace. Even if you don't use XLink or XML Events in the current incarnations of some of your SVG documents, including the bindings will prevent annoying errors if you decide to use them later and forget to add the bindings. This simply requires you to include the following three attributes on the root <svg> tag in your SVG documents.
<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     xmlns:ev="http://www.w3.org/2001/xml-events">
Be careful not to type xmlns:svg instead of just xmlns when you bind the SVG namespace. This is an easy mistake to make, but one that can break everything. Instead of making SVG the default namespace, it binds it to the namespace prefix 'svg', and this is almost certainly not what you want to do in an SVG file. A standards compliant browser will then fail to recognise any tags and attributes that don't have an explicit namespace prefix (probably most if not all of them) and fail to render your document as SVG.
绑定必要的名字空间
SVG 是带名字空间的 XML 方言,因此 SVG 文档中使用的所有的 XML 方言必须绑定到 XML 推荐标准中指定的名字空间。至少应当绑定 SVG XLink 名字空间,可能还要加上 XML Events 名字空间。即使目前在 SVG 文档中没有使用 XLink XML Events ,绑定它们也将避免将来的麻烦和错误。这仅仅需要在 SVG 根元素下添加三个属性。
<svg 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 名字空间的 xmlns 敲成 xmlns:svg ,这是个容易犯而且严重的错误。它将 SVG 元素绑定到带有 svg 前缀的名字空间,而不是缺省的名字空间,这显然不是你在 SVG 文档中期望的。在这种情况下,与标准兼容的浏览器(如果不是全部的话,至少是大多数)将无法识别没有显式名字空间前缀的 SVG 标签和属性 , 更无法将文档作为 SVG 渲染和显示。
It is quite common to see the style attribute used to specify properties in SVG. For example, you may see source code that specifies the fill and stroke properties as follows:
<circle style="fill:red; stroke:blue;" ... />
Usually this is simply gratuitous use of the style attribute, and something that should be avoided. Contrary to popular belief the style attribute (note, that's attribute , not element ) doesn't separate content from presentation, and unless you need to override properties set by a CSS selector, it is best to use the SVG formatting attributes instead. In other words it would be better to rewrite the previous code snippet as:
<circle fill="red" stroke="blue" ... />
Using the formatting attributes avoids the pitfalls that can be encountered when using CSS in SVG (see the following section, for example) and is generally considered to be better style. Unlike CSS and the style attribute, the formatting attributes are also supported in SVG Tiny, if that matters to you. Unfortunately many SVG authoring tools and human authors still make unnecessary use of the style attribute.
尽可能避免使用 style 属性
SVG 中设置某些属性值时使用 style 属性是很常见的。例如,设置 fill stroke 属性
<circle style="fill:red; stroke:blue;" ... />
通常使用 style 是个简便的的方法,然而是应当避免使用的方法。与流行的想法相反, style 属性(注意是属性而不是元素)没有将内容和显示分离,除非你需要覆盖 CSS 设置的属性,最好使用 SVG 格式的属性。也就是说上述代码应当改为:
<circle fill="red" stroke="blue" ... />
使用格式化属性避免了与 SVG 中使用的 CSS( 例子见下面)冲突的缺陷,一般也被认为是更好的风格。与 CSS style 属性不同, SVG Tiny 也支持格式化的属性(如果你关心 SVG Tiny 的话)。不幸的是很多 SVG 发布工具和作者还在不必要的使用 style 属性。
 
SVG uses styling properties to describe many of its document parameters such as fill and stroke-width . These properties can be set by CSS declarations or by presentation attributes (XML attributes that share the same name as the property and map to their corresponding CSS properties if the implementation supports CSS). For example, the display property is set on a circle by both:
<circle style="display:none;" ...>
and:
<circle display="none" ...>
For most properties there should be few interoperability problems, but frustratingly when properties are assigned a length the visual result can be completely different in the various SVG implementations. The problem arises because the SVG specification allows units to be omitted from lengths (in which case the lengths' units are the units of the current coordinate system (user units)), while on the other hand the CSS specification absolutely requires units to be explicity specified for all length values. The question is, are units required for lengths assigned to properties in SVG or not? Which specification takes precedence?
Unfortunately, this issue is a lot more compex than it first seems, and the answers to these questions are still disputed. The result is that implementations don't agree. Some require units, while others don't. The only way to avoid problems is to always specify a unit when assigning lengths to properties. Happily, in SVG, px units are defined to be equivalent to the units established by the current coordinate system (user units). In other words, wherever you would otherwise have omitted the unit from a length assigned to a property, use the px unit instead. For example, instead of writing:
<text stroke-width="2" style="font-size:20;" ...>
write:
<text stroke-width="2px" style="font-size:20px;" ...>
Note that units are only required for properties. Plain attributes such as the width or height attributes on the <rect> tag do not require a unit since they do not map to a CSS property. They can simply be assigned a number and it implicitly has the units of the current coordinate system.
According to the SVG 1.1 Property Index, there are only eight properties applicable to SVG 1.1 that accept a length value: stroke-width, stroke-dashoffset, font, font-size, baseline-shift, kerning, letter-spacing and word-spacing. It is these properties that you should be careful to always specify a length for.
为属性值分配长度时指定单位
SVG 使用风格属性描述很多文档参数,例如 fill stroke-width 。这些属性可以通过 CSS 声明或显示属性(在支持 CSS 的情况下,同名的 XML 属性映射到相应的 CSS 属性)。例如圆弧的显示属性可以分别描述为:
<circle style="display:none;" ...>
<circle display="none" ...>
对大多数属性来说很少存在互用性的问题,但设置长度的属性可能在不同的 SVG 实现中显示为完全不同的图形结果。造成这些问题的原因是, SVG 规范中允许属性省略长度单位(缺省长度单位为当前坐标系统长度单位(用户单位)),而另外一方面, CSS 规范需要显式声明所有的长度单位。问题是, SVG 到底需不需要指定长度单位,哪种规范的优先级更高呢?
这个问题比起初看起来更复杂一些,答案也是存在争议的。结果是 SVG 实现的不统一。一些实现要求设置单位,另外一些不要求。避免问题的唯一方法是设置属性时总是指定单位。令人高兴的是, SVG 中的 px 单位与当前坐标系统长度单位(用户单位)是相同的。也就是说,在所有省略长度单位的属性上可以使用 px 单位。例如
<text stroke-width="2" style="font-size:20;" ...>
应改为
<text stroke-width="2px" style="font-size:20px;" ...>
注意只对某些属性值需要指定单位,对普通属性,例如 <rect> 中的 width height 属性则不需要指定单位,因为这些属性并没有 CSS 属性映射。所以可以只设置一个数值,其单位隐式使用当前坐标系统的单位。根据 SVG1.1 属性索引,只有 8 种属性接受长度值: stroke-width, stroke-dashoffset, font, font-size, baseline-shift, kerning, letter-spacing word-spacing 。正是这些属性应当总是指定长度单位。
Use namespace aware DOM methods
The DOM Level 1 recommendation was created before the original Namespaces in XML recommendation was released, therefore DOM1 isn't namespace aware. This causes problems for namespaced XML such as SVG. To resove these problems, DOM Level 2 Core added namespace aware equivalents of all the applicable DOM Level 1 methods. When scripting SVG it is important to use the namespace aware methods. The table below lists the DOM1 methods that shouldn't be used in SVG along with their equivalent DOM2 counterparts that should be used instead.

DOM1 (don't use)
DOM2 (use these instead!)

The first argument for all the DOM2 namespace aware methods must be the "namespace name" of the element or attribute in question. For SVG elements this is 'http://www.w3.org/2000/svg'. However, note carefully: the Namespaces in XML 1.1 recommendation states that the namespace name for attributes without a prefix does not have a value. In other words you must use null as the namespace name for SVG attributes . As a result, to create an SVG 'rect' element using createElementNS you must write:
createElementNS('http://www.w3.org/2000/svg', 'rect');
However, to retrieve the value of the 'x' attribute on an SVG 'rect' element you must write:
getAttributeNS(null, 'x');
Note that this is not the case for attributes from other (non-SVG) namespaces such as the xlink:href attribute which use a namespace prefix. Since it has a namespace prefix in the markup ("xlink") it's namespace name is the value that was assigned to that prefix, 'http://www.w3.org/1999/xlink'. Hence to get the value of the xlink:href attribute of an 'a' element in SVG you would write:
getAttributeNS('http://www.w3.org/1999/xlink', 'href');
In summary the rule is simple. For elements with or without a namespace prefix, and for attributes with a namespace prefix, the namespace name is the namespace URI of the element/attribute in question. For attributes without a namespace prefix the namespace name is null.
使用名字空间敏感的 DOM 方法
DOM Level 1 推荐标准在 XML 标准中出现名字空间之前发布,因此 DOM1 不是名字空间敏感的。这就引发了名字空间化 XML 中的问题,例如 SVG 。为解决这些问题, DOM Level 2 核心添加了与 DOM Level 1 对等的,但是名字空间敏感的方法。编写 SVG 时应使用名字空间敏感的方法。下表列出了不应再使用的 DOM Level 1 方法以及与之对应的并推荐使用的 DOM2 方法。

DOM1 ( 不再使用 )
DOM2 ( 推荐使用 )
getElementsByTagNameNS ( 也应用在元素上 )

所有 DOM2 名字空间敏感方法的第一个参数必须是所操作元素或属性的“名字空间名称”。对 SVG 元素是“ http://www.w3.org/2000/svg ”,然而,请注意: XML 1.1 推荐标准中的名字空间规定,不带前缀属性的名字空间名称为空。也就是说,对 SVG 属性必须使用 null 名字空间。因此,使用 createElementNS 创建一个 SVG rect 元素必须写为:
createElementNS('http://www.w3.org/2000/svg', 'rect');
然而取得该“ rect 元素中的“ x ”属性值必须写为:
getAttributeNS(null, 'x');
注意对其它(非 SVG )名字空间的属性并不适用。例如 xlink:href 使用了一个名字空间前缀,因为存在一个名字空间前缀标记( xlink ),名字空间名称为前缀的值即 http://www.w3.org/1999/xlink ,因此取得元素中 xlink:href 属性值应写为:
getAttributeNS('http://www.w3.org/1999/xlink', 'href');
总体说来规则是比较简单的。对带有或不带有名字空间前缀的元素,以及带有名字空间前缀的属性,名字空间名称为元素或属性名字空间的 URI 。对不带有名字空间前缀的属性,名字空间名称为 null
Don't use Adobe's getter and setter extensions
Long, long ago when Adobe first released their SVG viewer plug-in, Netscape 4 still had enough users that it was important to be compatible with it. To do this it seems it was necessary to extend the ECMAScript interfaces and provide corresponding getters and setters for all the properties defined by the specification. As a result in ASV it is possible to write code like this:
evt.getTarget().getOwnerDocument().getDocumentElement();
when the DOM and SVG specifications actually define properties, not methods, so the correct way to write this code is:
 
evt.target.ownerDocument.documentElement;
The problem is that no one else supports ASV's getter and setter extensions. Scripts that uses them will not work in other SVG implementations. Happily Netscape 4 is now irrelevant for most of us, and since ASV supports the properties too, new SVG scripts can conform to the standards and work in all SVG implementations by using the properties. (In fact old code could, and should, be updated too.)
It is difficult to give a list of what is and isn't an ASV extension since there are so many properties. If you aren't familiar enough with the specifications to know which getters and setters are defined by the W3C and which are ASV extensions, be sure to test your scripts using another SVG implementation such as Mozilla Firefox or Batik. If you get errors relating to getters or setters try using properties instead and see if that fixes things. You can also search for getter and setter names in the SVG, DOM2 Core, DOM2 Events and DOM2 Style IDL. If you can't find them in any of those documents they probably aren't part of any W3C standard.
不要使用 Adobe getter setter 扩展
在很久很久以前, Adobe 第一次发布 SVG viewer 插件时, Netscape 4 仍然拥有大量的用户,所以必须与之保持兼容。为达到这个目的,必须扩展 ECMAScript 接口并为规范中所有属性提供相应的 getters setters 方法。因此在 ASV 中代码可能如下所示:
 
evt.getTarget().getOwnerDocument().getDocumentElement();
 
实际上 DOM SVG 规范定义的是属性,而不是方法,因此正确的写法应为:
 
evt.target.ownerDocument.documentElement;
 
问题的原因是除 ASV 外,没有其它 SVG 实现支持 getters setters 方法扩展。使用这些扩展方法的代码无法在其它 SVG 实现中使用。另人高兴的是现在 Netscape 4 已经不再重要,而且 ASV 也支持使用属性,因此新的 SVG 脚本应遵循标准,使用属性,以便在所有 SVG 实现中工作。(实际上旧的代码也可以,而且应当进行升级)
 
因为存在太多这种扩展属性,所以很难给出一个列表以说明哪些是 ASV 扩展,哪些不是。如果你不清楚哪些 getters setters 方法是 W3C 规范中定义的,哪些是 ASV 扩展的,请使用 ASV 以外的一种 SVG 实现对代码进行测试,例如 Mozilla Firefox Batik 。如果发现与 getters setters 方法相关的错误,试试使用属性是否能够解决这些问题。也可以在 SVG, DOM2 核心, DOM2 事件和 DOM2 风格 IDL 文档中搜索相关的 getters setters 方法名称,如果在这些文档中找不到这些名字,它们很可能不是 W3C 标准中的一部分。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值