使用HTML5和SVG应对僵尸末日





5.00/5 (1投票)
本文是三部曲系列的第一篇,该系列将探讨 HTML5 对内联 SVG 元素(如图像、文本、形状和路径)的支持。
随着浏览器对 HTML5 的支持不断加快,开发者们发现了越来越多创建优雅、高度响应式 UI 的方法。对于可缩放矢量图形 (SVG) 而言,旧的又焕发新生,并且相当酷炫。
SVG 规范已经存在一段时间了。自 1999 年开始开发以来,该规范,或者更准确地说是一系列规范,描述了一种基于 XML 的矢量图形文件格式。SVG 块定义了矢量图像的各个组件,例如路径、形状、填充、描边和其他特征。这为可能已在 Adobe Illustrator 或 Inkscape 中创建并导出为栅格格式的某些类型的图形提供了一种轻量级的选择。它还承诺在动态操作图像方面具有广泛的潜在功能——因此有了 SVG 的“可缩放”一词。
随着 HTML5 标准的广泛采用,浏览器正在将 SVG 推向新的方向,例如强调内联 SVG 的 <svg> 标签,使用 CSS 进行样式设置,以及开放 DOM,以便可以使用 JavaScript 在客户端创建或操作 SVG 图像。
为了演示,本系列教程将旨在造福人类两方面。一、将介绍跨浏览器兼容的 SVG 示例,同时指出 SVG 采用的一些差异。二、将或多或少准确地预测一个人能否在僵尸末日中生存下来。
第一步:准备
开始之前,了解目标浏览器很有帮助。虽然所有现代浏览器在一定程度上都支持 SVG,但其实现仍有许多不同之处——有些细微,有些重大。例如,同步多媒体集成语言 (SMIL) 规范描述了如何通过 <animate> 元素为 SVG 设置动画。这为开发者提供了机会,让他们能够添加用户交互和独立属性随时间的变化,而无需离开 <svg> 元素。不幸的是,并非所有浏览器都已支持 SVG/SMIL 动画(尽管确实存在其他形式的 SVG 动画 [http://msdn.microsoft.com/en-us/library/gg193985(v=vs.85).aspx])。
"Can I Use…" (https://caniuse.cn/) 提供了所有主要桌面和移动 Web 浏览器之间详尽的并排比较,并指出其哪些版本支持各种 HTML5 功能。对于深入了解特定的 SVG 功能尤其有用,例如使用 内联 SVG 和 SVG 滤镜效果,这些功能刚刚添加到 Internet Explorer 10 中。
第二步:创建 SVG 元素
这个特定的 SVG 僵尸末日生存预测器将使用三个独立的 SVG 元素:一个用于“城市”的面板,一个用于风险因素的控制面板,以及一个用于预测仪表本身的面板。
首先,创建一个 600x400 的根元素,名为“cityBox”
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Planning for the Zombie Apocalypse with HTML5 and SVG</title> <script> </script> <style> </style> </head> <body> <svg id="cityBox" width="600" height="400"> </svg> </body> </html>
瞧。一个看不见的盒子。现在是僵尸世界的冬天。可以通过 CSS 样式添加边框,无论是通过 `<svg>` 元素本身的“style”属性,还是通过在页眉中定义样式,如下所示:
<style> #cityBox { border: 1px solid #000000; float: left; } </style>
第三步:添加文本
虽然开发者有很多处理页面上文本的方法,但通过 SVG 进行处理为许多有趣的选项打开了大门,例如更改字符偏移、拉伸文本、旋转句子或将文本拟合到路径。
但在尝试这些之前,请为 `cityBox` 元素添加一个标题:
<svg id="cityBox" width="600" height="400"> <text x="300" y="50"> Surviving the Zombie Apocalypse </text> </svg>
x,y 坐标定义了第一个字符的基线。从这个例子中删除它们,文本几乎会从 SVG 元素的顶部消失。
SVG 文本元素的样式有三种:“style”属性、已定义的样式或单独的 SVG 属性。但请注意,某些属性似乎会根据所使用的方法和浏览器而表现不佳。例如,定义“`font-family`”无论放在哪里,对所有浏览器都有效。但是,“`font-size`”的实现不一致。在 Chrome 或 Internet Explorer 中,在 <style> 页眉中定义它不起作用。在 `<text>` 元素本身的“style”属性中定义它,如以下示例所示,在 Chrome 中有效,但在 Internet Explorer 中无效:
<text x="300" y="50" id="titleText" style="font-size: 36;">
在两个浏览器中都有效的唯一技术是在 `<text>` 标签内将“`font-size`”定义为属性。因此,为了演示目的和最大的跨浏览器兼容性,此处将这样做。
<text x="300" y="50" font-family="sans-serif" font-size="36" text-anchor="middle" stroke="#000000" fill="#000000">
请注意,与 CSS 一样,描边和填充颜色可以使用颜色名称或十六进制值。还要注意“`text-anchor`”属性,该属性定义文本相对于 x,y 原点的位置。由于它默认为“left”,因此此示例将其设置为“`middle`”,并定义原点为 `<svg>` 元素的中心。
关于“text-anchor”和文本的另一个有趣的怪癖是:如果 <text> 元素超出了 `<svg>` 元素的边界,接下来会发生什么取决于浏览器。在 Chrome 中,<svg> 元素边缘之外的任何内容都会被剪裁。然而,在 Internet Explorer 中,文本会延伸到 <svg> 元素的边界之外。
与其他矢量图像一样,SVG 文本同时具有描边和填充。默认情况下,`<text>` 元素显示黑色填充,没有描边。在此示例中,添加了一个黑色描边,如**图 2** 所示。它不仅加粗了文本,而且正如本系列稍后将看到的,描边的颜色可以设置为动画,以产生有趣的效果。
第四步:图像
虽然 SVG 的目的表面上是创建图形,但有时将现有 SVG 图形合并到页面上比从头开始创建要好。当图形由矢量设计软件(如 Microsoft Expression Design、Adobe Illustrator 或 Inkscape)创建,或者来自 SVG 剪贴画库(如 Wiki Commons)时,尤其如此。
僵尸末日生存预测器的城市面板最终将显示僵尸末日的所有元素。但首先,它只有一个人类。一个孤单、惊恐的人类拼命逃跑。这个人最初来自 Inkscape,并保存为 SVG 文件(human.svg)。(注意:本教程中使用的所有 .svg 图形文件均来自 http://openclipart.org,可从 ______ 下载。)
`<image>` 元素可以以几种不同的方式工作,其中一种在浏览器中受支持,另一种则不支持。
首先,最简单的方法。在 `<svg>` 元素内,添加以下内容:
<image id="human" x="275" y="175" width="50" height="50" xlink:href="human.svg" />
此标签添加了外部引用的 svg 文件(“*human.svg*”),并将其放置在 275,175 的位置,这是在补偿图像尺寸后城市的中心。说到尺寸,图像随后被缩放到 50x50。在这种情况下,无需知道原始文件大小。图像会自动转换,使其最大尺寸与指定参数匹配,另一尺寸按比例缩放。结果应类似于**图 3**。
不幸的是,并非总是如此。在许多浏览器(如 Firefox 和 Internet Explorer)中,宽度和高度属性定义的是视图区域而不是图像大小,结果是从左上角坐标开始的裁剪图像,如**图 4** 所示。
有两种方法可以解决此问题。一种是编辑图像本身并将其调整为所需的尺寸。但这在某种程度上削弱了使用可缩放图形的目的。因此,将应用变换。
在文本编辑器中打开“*human.svg*”文件会显示元数据中的当前图像尺寸,在本例中为:
width="342.70523" height="482.82114"
但不要被这些属性可以手动编辑并且一切都会正常的想法所迷惑。事实并非如此。由于 SVG 文件中嵌入了其他 XML 数据,更改宽度/高度元数据将导致图像蒙版,该蒙版根据浏览器表现出不可预测的行为。
相反,使用宽度和高度值创建一个新的 `<image>` 元素:
<image id="human" x="2750" y="1750" width="343" height="483" transform="scale(.10,.10)" xlink:href="human.svg" />
在此示例中,宽度和高度设置为图像的实际值(四舍五入)。将最大尺寸(高度:483)缩小到 10% 会创建一个接近 50x50 的图像。但请注意,“transform”属性也会影响元素原点。因此,原始 x,y 坐标 275,175 需要更改为 2750,1750(将原始值除以缩放比例:275 / .1 = 2750),以保持相同的放置。这在 Internet Explorer 中产生了图 5。
现在,那个惊慌失措的小人类在每个浏览器中看起来都一样。或者至少在本教程测试的所有浏览器中都是如此。
第五步:基本形状
现在一些比较棘手的内容已经就位,控制面板将回归大多数 SVG 教程开始的基础:简单形状。SVG 定义了几个形状元素:`<line>`、`<rect>`、`<circle>`、`<ellipse>`、`<polygon>` 和 `<polyline>`。还可以使用 `<path>` 元素创建全新的形状。
预测器控制面板将由用于缩放数量的三角形“步进”控件、文本标签以及两个带有图像的圆形组成。首先,创建 `<svg>` 元素及其样式(为方便开发,目前有一个 1 像素的边框)。
在 <style> 下添加以下内容:
#controlPanelBox { border: 1px solid #000000; float: left; }
在页面的 <body> 中添加:
<svg id="controlPanelBox" width="400" height="400"> </svg>
创建三角形时,`<polygon>` 和 `<path>` 元素都能很好地工作。以下两个元素看起来相同,如**图 6** 所示:
<polygon points="50,50 100,25 100,75" stroke="black" stroke-width="1" fill="red" /> <path d="M 50 50 L 100 25 L 100 75 L 50 50" stroke="black" stroke-width="1" fill="red" />
使用 `<polygon>` 元素时,多边形的每个点都绝对定义,形状会自动填充。使用 `<path>` 元素时,原点在数据 (“d”) 属性中定义为 Moveto (“M”) 值。每个后续的 Lineto (“L”) 点绘制路径,最后以原点结束。最后一点闭合路径并创建多边形形状。如果没有它,红色填充仍然是三角形的形状,但描边将缺少最后一条腿。
路径的一个优点是,通过使用小写字母而不是大写字母,`Moveto` 和 `Lineto` 值可以是相对的。这允许通过简单地更改 `Moveto` 值来轻松移动路径。例如,以下两个元素会产生相同的形状,也与**图 6** 相同:
<path d="M 50 50 L 100 25 L 100 75 L 50 50" stroke="black" stroke-width="1" fill="red" /> <path d="M 50 50 l 50 -25 l 0 50 l -50 -25" stroke="black" stroke-width="1" fill="red" />
因此,虽然多边形通常更容易创建,但相对路径对于控制面板更有意义。将使用多个三角形,因此可以创建两个版本(镜像图像),然后通过更改 M 值来复制和重新定位它们。
每组控件还将包含一对 `<text>` 元素,用作标签和文本字段。后者将在本系列的后续部分根据与控件的交互通过 JavaScript 进行修改。
因此,对于控制面板中的第一个参数,即现有的人口,元素集应如下所示:
<path id="zombieLess" d="M 50 50 l 50 -25 l 0 50 l -50 -25" stroke="black" stroke-width="1" fill="red" /> <text id="zombieLabel" font-size="15" font-family="sans-serif" text-anchor="middle" fill="red" x="175" y="25"> City Population (000s) </text> <text id="zombieText" font-size="25" font-family="sans-serif" text-anchor="middle" fill="black" x="175" y="60"> 0 </text> <path id="zombieMore" d="M 300 50 l -50 -25 l 0 50 l 50 -25" stroke="black" stroke-width="1" fill="red" />
作为一项额外的好处,元素可以嵌套在 Group `<g>` 元素内。整个组可以命名、样式化和操作,结果将应用于组中的每个成员。在这种情况下,每个控件都将分组,仅用于组织。
得益于相对路径定义,快速复制粘贴即可创建两个相同的控件集。在更改 Moveto 点、`<text>` 原点、ID 和文本内容后,页面现在有三个步进控件:
<g id="zombieGroup"> <path id="zombieLess" d="M 50 50 l 50 -25 l 0 50 l -50 -25" stroke="black" stroke-width="1" fill="red" /> <text id="zombieLabel" font-size="15" font-family="sans-serif" text-anchor="middle" fill="red" x="175" y="25"> City Population (000s) </text> <text id="zombieText" font-size="25" font-family="sans-serif" text-anchor="middle" fill="black" x="175" y="60"> 0 </text> <path id="zombieMore" d="M 300 50 l -50 -25 l 0 50 l 50 -25" stroke="black" stroke-width="1" fill="red" /> </g> <g id="mallGroup"> <path id="mallLess" d="M 50 150 l 50 -25 l 0 50 l -50 -25" stroke="black" stroke-width="1" fill="red" /> <text id="mallLabel" font-size="15" font-family="sans-serif" text-anchor="middle" fill="red" x="175" y="125"> # of Shopping Malls </text> <text id="mallText" font-size="25" font-family="sans-serif" text-anchor="middle" fill="black" x="175" y="160"> 0 </text> <path id="mallMore" d="M 300 150 l -50 -25 l 0 50 l 50 -25" stroke="black" stroke-width="1" fill="red" /> </g> <g id="redneckGroup"> <path id="redneckLess" d="M 50 250 l 50 -25 l 0 50 l -50 -25" stroke="black" stroke-width="1" fill="red" /> <text id="redneckLabel" font-size="15" font-family="sans-serif" text-anchor="middle" fill="red" x="175" y="225"> Rednecks </text> <text id="redneckText" font-size="25" font-family="sans-serif" text-anchor="middle" fill="black" x="175" y="260"> 0 </text> <path id="redneckMore" d="M 300 250 l -50 -25 l 0 50 l 50 -25" stroke="black" stroke-width="1" fill="red" /> </g>
对于最后一组控件,此应用程序需要最基本的形状:圆。`<circle>` 元素通过定义三个主要属性来工作:中心 x (“`cx`”)、中心 y (“`cy`”) 和半径 (“`r`”)。默认情况下,填充为黑色,描边不存在。但是:
由于这是一个切换控件,因此当前的选择将由粗黑的描边指示,而不活动的选定项是细黑的描边。两者都有白色填充,形成一个可能容纳图像的圆。或者一个僵尸。
<circle id="slowCircle" cx="75" cy="325" r="40" stroke="red" fill="white" stroke-width="4" /> <circle id="fastCircle" cx="275" cy="325" r="40" stroke="black" fill="white" stroke-width="2" />
僵尸图像的处理方式与人类图像相同——尺寸定义为图形的实际尺寸,然后应用“transform”属性将其缩放到原始尺寸的 0.16。此缩放也适用于 x,y 原点。此外,由于 SVG 元素按顺序渲染,因此图像需要显示在圆形之后:
<circle id="slowCircle" cx="75" cy="325" r="40" stroke="red" fill="white" stroke-width="4" /> <image id="slowZombie" x="375" y="1875" width="175" height="304" transform="scale(.16,.16)" xlink:href="zombie.svg" /> <circle id="fastCircle" cx="275" cy="325" r="40" stroke="black" fill="white" stroke-width="2" /> <image id="fastZombie" x="1630" y="1875" width="175" height="304" transform="scale(.16,.16)" xlink:href="zombie.svg" />
最后,添加一对标签/文本字段,并将整个内容分组:
<g id="speedGroup"> <circle id="slowCircle" cx="75" cy="325" r="40" stroke="red" fill="white" stroke-width="4" /> <image id="slowZombie" x="375" y="1875" width="175" height="304" transform="scale(.16,.16)" xlink:href="zombie.svg" /> <text id="speedLabel" font-size="15" font-family="sans-serif" text-anchor="middle" fill="red" x="175" y="315">Zombie Speed</text> <text id="speedText" font-size="25" font-family="sans-serif" text-anchor="middle" fill="red" x="175" y="350">Slow</text> <circle id="fastCircle" cx="275" cy="325" r="40" stroke="black" fill="white" stroke-width="2" /> <image id="fastZombie" x="1630" y="1875" width="175" height="304" transform="scale(.16,.16)" xlink:href="zombie.svg" /> </g>
在开发到目前为止,僵尸末日生存预测器应如**图 11** 所示:
下一步
显然,任何在当前状态下使用预测器的人都将死路一条。或者说,根据情况,是僵尸肉。或者只是食物。本系列的下一步将在此处介绍的现有控件的基础上,添加一个用于预测比例的面板,一些动画和一些 JavaScript,让按钮发挥作用。
同时,到目前为止的项目可以在以下网址查看:
http://justinwhitney.com/zombies/zombies_part1.htm
SVG 在实践中的更多示例可以在以下网址查看:
SVG 骰子
http://ie.microsoft.com/testdrive/Performance/SVGDice/Default.xhtml#
SVG 渐变背景生成器
http://ie.microsoft.com/testdrive/Graphics/SVGGradientBackgroundMaker/Default.html
Internet Explorer 10 中的 SVG 滤镜效果
http://blogs.msdn.com/b/ie/archive/2011/10/14/svg-filter-effects-in-ie10.aspx
SVG 直升机
http://ie.microsoft.com/testdrive/Performance/Helicopter/Default.xhtml
本文由 Justin Whitney 撰写。Justin 在东德克萨斯州农村的一个掩体里构建网站和移动应用程序,同时为文明的终结做准备。