SVG交互性
目录
什么是SVG?
-
是指可伸缩矢量图形
-
用来定义用于网络的基于矢量的图形
-
XML 格式定义图形
-
图像在放大或改变尺寸的情况下其图形质量不会有所损失
-
是万维网联盟的标准
-
与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体
语法
//声明文档格式 xml
//version 版本
//standalone 外部引用
<?xml version="1.0" standalone="no"?>
//文档类型 svg
//引用外部SVG DTD 文档
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
//绘制svg图 默认宽高100% 版本设置
//xmlns命名空间
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
//绘制一个圆形 起始点100,50 半径40 边框宽2颜色黑色 填充红色
<circle cx="100" cy="50" r="40" stroke="black"stroke-width="2" fill="red"/>
</svg>
将文件放到.txt文件中,保存成为一个.svg的文件即可。
SVG在网页中的使用方式
- 图片导入
- 嵌入iframe
- 内嵌SVG
- 嵌入<embed>
- 嵌入<object>
- a标签中
a.图片导入
<img src="circle1.svg" type="image/svg+xml" />
b.使用<iframe>标签
语法:<iframe src="circle1.svg" type="image/svg+xml"></iframe>
优势:所有主要浏览器都支持,并允许使用脚本
缺点:不推荐在HTML4和XHTML中使用(但在HTML5允许)
c.直接在HTML嵌入SVG代码
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
</svg>
d.使用<embed>标签
语法:<embed src="circle1.svg" type="image/svg+xml" />
优势:所有主要浏览器都支持,并允许使用脚本
缺点:不推荐在HTML4和XHTML中使用(但在HTML5允许)
e.使用 <object> 标签
语法:<object data="circle1.svg" type="image/svg+xml" ></object>
优势:所有主要浏览器都支持,并支持HTML4,XHTML和HTML5标准
缺点:不允许使用脚本
f.使用 <a> 标签
<a href="circle1.svg">View SVG file</a>
SVG交互
SVG 中的交互性可以分为三个领域 -- 链接、事件和脚本。
注意:要查看本技巧中的 SVG 文档,需要有一个 SVG 查看程序,可以在 参考资料中找到这种查看程序(还有一个包括所有相关文件的 .zip 文件)。
链接
最基本的交互形式是链接。在 SVG 中,通过一个 <a>
标签提供链接,这与 HTML 链接的方式几乎相同。将<a>
标签与一个 xlink:href
属性结合使用便可以建立一个链接。在 <a>和
</a>
标签之间的所有内容都作为链接的一部分。清单1展示了一个例子,它有三个元素,设置为链接到三个不同的 URL。 单击这里以在浏览器中查看它们。
文本、矩形和多边形元素都有到不同页面的链接,这表明所有 SVG 元素 -- 不管是文本、圆还是不规则的多边形 -- 都可以作为一个链接。注意,如果将鼠标移动到这些元素上面,指针会相应地发生改变,表明这是一个链接。
其功能与 HTML 中的 image map(或者 hotspot)基本上相同。不过,在 HMTL 中这会是一个很麻烦的过程,要用专门的软件在一个图像上手工绘制热点 -- 如果这个图像或者链接改变了,那么更新它们会非常麻烦。在 SVG 中,定义和维护链接则容易得多,这主要是因为链接可以随着 SVG 内容动态移动。
清单1. 链接
<svg>
<a xlink:href="http://www.w3.org//Graphics//SVG//Overview.htm8">
<rect x="10" y="10" width="100" height="30" rx="10" ry="10"
style="fill:lightgrey"/>
<text x="30" y="30" font-size="12">Click here</text>
</a>
<a xlink:href="http://www.ibm.com//developerworks/">
<circle cx="100" cy="100" r="50" style="fill:grey"/>
<text x="80" y="100" font-size="12">Or here</text>
</a>
<a xlink:href="http://www.ibm.com/" target="new">
<polygon
points="60 160,165 172,180 60,290 290,272 280,172 285,250 255"
style="fill:dimgrey"/>
<text x="160" y="200" font-size="12">Or even here</text>
</a>
</svg>
注意在多边形的 xlink
中使用的 target=new
属性。它指示查看程序在单击这个元素时打开一个新的浏览器窗口。
事件
SVG 支持鼠标单击、鼠标移动和鼠标按下这样的用户鼠标事件。清单2展示了一个例子:
清单2. 使用鼠标的交互性
<svg>
<rect x="10" y="10" width="140" height="140" rx="5" ry="5"
style="fill:lightgrey">
<set attributeName="fill" from="lightgrey" to="red"
begin="mouseover" end="mouseout"/>
</rect>
<text x="200" y="75" font-size="30">Move over me and click
<set attributeName="font-size" from="30" to="35"
begin="mouseover" end="mouseout"/>
<set attributeName="fill" from="black" to="red"
begin="mousedown" end="mouseup"/>
</text>
</svg>
矩形和文本元素对不同的事件 -- 如移动鼠标和单击 -- 做出反应,产生一种简单的滚动效果。试着将鼠标移动到元素上面以观看这些效果。任何可以应用到元素上的 SVG 属性 -- 如填充颜色、笔划宽度、大小和透明度 -- 都可以以这种方式改变。
文字元素可以对两种事件做出反应 -- mouseover
和 mousedown
。这表明可以对同一个元素指定多个事件。SVG 支持许多不同的事件 -- 有关所有事件类型的完整列表可以参看 参考资料中的 W3C 的 SVG 站点。
如果希望一个元素上的事件可以引发对另一个元素的操作,可以对 SVG 元素指定 id
属性,然后引用它们。清单3展示了一个例子。
清单3: 改变另一个元素的属性
<svg>
<rect id="changeToRed" x="20" y="20" width="25" height="25" rx="5"
ry="5" style="fill:lightgrey"/>
<text x="50" y="35" font-size="14">Move over for red text</text>
<rect id="bigText" x="20" y="60" width="25" height="25" rx="5"
ry="5" style="fill:lightgrey"/>
<text x="50" y="75" font-size="14">Move over for big text</text>
<rect id="bigRedText" x="20" y="100" width="25" height="25" rx="5"
ry="5" style="fill:lightgrey"/>
<text x="50" y="115" font-size="14">Click me for big red text</text>
<text id="changingText" x="250" y="100" font-size="30"
fill="black">Change me
<set attributeName="fill" from="black" to="red"
begin="changeToRed.mouseover" end="changeToRed.mouseout"/>
<set attributeName="font-size" from="14" to="50"
begin="bigText.mouseover" end="bigText.mouseout"/>
<set attributeName="font-size" from="14" to="50"
begin="bigRedText.click" end="bigRedText.mouseout"/>
<set attributeName="fill" from="black" to="red"
begin="bigRedText.click" end="bigRedText.mouseout"/>
</text>
</svg>
单击这里可以在浏览器中观看效果。当鼠标移动到不同的矩形上时,文本就会改变。有三个矩形被指定了各自的 id
属性,文字的 set
元素通过“ id.eventName
”引用这些属性。触发矩形的事件时,文本的属性就会相应地改变。
还可以用一个动画响应事件。清单4展示了这样的一个例子:
清单4. 开始一个动画
<svg>
<rect x="20" y="20" width="250" height="250" rx="5" ry="5"
style="fill:red">
<animate attributeName="opacity" from="1" to="0"
begin="click + 1s" dur="1s" fill="restore" />
</rect>
<circle cx="250" cy="250" r="100" style="fill:blue">
<animate attributeName="fill" from="blue" to="green"
begin="mouseover" dur="2s" fill="restore" />
</circle>
</svg>
单击这里以便观看效果。单击矩形时,它会淡出,在圆形上面移动鼠标时,它的颜色会改变。注意可以在 begin
属性中使用“ +Xs
”使动画延迟开始。
键按下
虽然 SVG 上的大部分交互是通过鼠标进行的,但是 SVG 也支持键盘输入。这是通过事件处理程序accessKey
实现的,如清单5所示。
清单5. 捕获键按下
<svg>
<rect x="20" y="20" width="100" height="100" rx="5" ry="5" style="fill:red">
<animate attributeName="opacity" from="1" to="0" begin="accessKey(1)" dur="3s" fill="restore" />
</rect>
<rect x="140" y="20" width="100" height="100" rx="5" ry="5" style="fill:red">
<animateTransform attributeName="transform" type="rotate"
from="0" to="90" begin="accessKey(2)" dur="3s"/>
</rect>
<rect x="260" y="20" width="100" height="100" rx="5" ry="5" style="fill:red">
<animateColor attributeName="fill" from="red" to="green" begin="accessKey(3)" dur="3s" />
<animate attributeName="y" from="20" to="100" begin="accessKey(
)" dur="3s" fill="restore" />
</rect>
</svg>
单击这里以观看效果。三个矩形设置为响应键盘上的数字键 1、2 和 3。试一试按下每一个键,并观察图像相应的反应。
可以设置一个元素响应任意数量的不同的键。注意第三个矩形设置为监听两个键按下。第三个矩形上的第二个 accessKey
处理程序设置为监听键 ( )
-- 您可能认出它就是回车键(Enter)的标准 HTML 编码。要指定任何特殊字符或者空格字符,必须使用 &#XX
这样的 HTML 编码格式,其中 XX
是 ASCII 字符编码。
脚本
到目前为止我只讨论了用 SVG 支持的内置功能响应事件的基本方法。虽然可以只使用这些功能完成很多工作,但是要实现更高级的效果就需要使用脚本了。SVG 支持像 VBScript 和 JavaScript 这样的脚本语言,对于这里的例子,我将使用 JavaScript。
要让一个 SVG 对象对脚本中的事件作出响应,要在触发器名上加前缀 on
,这样 click
就变为onclick
, mouseover
就变为 onmouseover
,等等。清单6展示了一个 SVG 脚本的例子。
清单6. 用 JavaScript 编写 SVG 脚本
<svg>
<script type="text/javascript">
<![CDATA[
var redVal=0;
var greenVal=0;
var blueVal=0;
function changeCol(evt){
var targetshape = evt.target;
redVal = Math.round(Math.random()*255);
greenVal = Math.round(Math.random()*255);
blueVal = Math.round(Math.random()*255);
targetshape.setAttribute("fill", "rgb(" + redVal + "," + greenVal + "," + blueVal + ")");
}
]]>
</script>
<circle cx="200" cy="200" r="100" fill="blue" onclick="changeCol(evt)" />
</svg>
下面逐步分析 清单6:
- 编写 SVG 脚本的第一步是通知查看程序不再使用 SVG,而是使用脚本语言。还必须用
type
属性定义使用哪种脚本语言编码。在这里它设置为text/javascript
。 -
<![CDATA[
是 XML 命令,它告诉查看程序停止解析代码,并读取接下来的块中的代码,这里的代码是字符数据的形式。这可以防止查看程序将括号和其他特殊字符按 SVG 元素处理,并使脚本编写更容易。 - 现在就可以开始脚本了。首先,定义三个变量:
redVal
、greenVal
和blueVal
。这些变量分别具有red、green 和 blue 值,它们将在函数中用到。这个函数名为changeCol
,它带有一个参数(evt)。
evt
是一个 SVG 保留字,它描述刚发生的事件。这里,evt
方法称为getTarget(),
这个方法返回对触发该事件的 SVG 对象的一个引用。这个引用被存储在变量targetShape
中。 - 用简单的 JavaScript 函数
Math
生成三个值在 0 到 255 之间的随机数。 - 最后,对
targetshape
调用setAttribute
方法。用前一步中生成的三个随机数将该对象的fill
属性设置为一个 RGB 值(如rgb(150,200,50)
)。 - 关闭
CDATA
块和脚本后,返回 SVG。画出一个圆,通过onClick
元素,在单击时让它调用函数changeCol(evt)。
单击这个圆时,每次单击它时填充都会变为一个随机颜色。
当一个函数要应用到多个 SVG 元素时,脚本是最有用的。例如,可以在清单6中添加一个矩形,如下所示
<svg width="500" height="500" version="1.1">
<script type="text/javascript">
<![CDATA[
var redVal = 0;
var greenVal = 0;
var blueVal = 0;
var count = 0;
function changeCol(evt) {
var targetshape = evt.target;
redVal = Math.round(Math.random() * 255);
greenVal = Math.round(Math.random() * 255);
blueVal = Math.round(Math.random() * 255);
targetshape.setAttribute("fill", "rgb(" + redVal + "," + greenVal + "," + blueVal + ")");
console.log(count++);
}
function changeEdg(evt) {
var targetshape = evt.target;
targetshape.setAttribute('rx', "100");
targetshape.setAttribute('ry', "100");
}
function resetEdge(evt) {
var targetshape = evt.target;
targetshape.setAttribute("rx", '0');
targetshape.setAttribute('ry', "0");
}
]]>
</script>
<circle cx="270" cy="110" r="30" fill="blue"
onclick="changeCol(evt)">
</circle>
<rect x="300" y="10" width="50" height="50" fill="blue"
onclick="changeEdg(evt)"></rect>
<rect x="300" y="80" width="50" height="50" fill="red"
onclick="resetEdge(evt)"></rect>
</svg>
如果查看源代码,您会看到三个方法: changeCol
、changeEdge
和 resetEdge
。试着将鼠标移动矩形上面并单击。所有矩形都设置为响应 onclick
、onmouseover
和 onmouseout
事件,它们为此调用的是同一个脚本函数。还要注意 onload
属性:第一次装载 SVG 文档时要调用这个属性,它对于您的 SVG 初始化很有用。单击时,这个矩形会与前面的圆形一样调用同一个脚本改变其颜色。
交互文本
在 SVG 中创建交互文本比您想象中的要复杂一些。在定义文本元素时,显示的文本是文本元素的子元素,而不是像 font-size
这样的属性,因此不能像前面那样简单地调用 setAttribute
来修改其内容。相反,必须创建一个新的文本元素,并用它替换当前的文本元素。清单7展示了一个例子。
清单7. 编写文本变化的脚本
<svg>
<script type="text/javascript">
<![CDATA[
function changeText(evt){
//外部引用svg写法 document换成“svgDocument”
targetXtext=document.getElementById("XPos");
targetYtext=document.getElementById("YPos");
//外部引用svg写法 clientX换成“getClientX()”
var XPos = evt.clientX;
var YPos = evt.clientY;
var newXPosText = document.createTextNode("X Position : " + XPos);
var newYPosText = document.createTextNode("Y Position : " + YPos);
//外部引用svg写法 firstChild换成“getFirstChild()”
targetXtext.replaceChild(newXPosText,targetXtext.firstChild);
targetYtext.replaceChild(newYPosText,targetYtext.firstChild);
}
function changeTextNotOver(evt){
targetXtext=document.getElementById("XPos");
targetYtext=document.getElementById("YPos");
var newXPosText = document.createTextNode("X Position : Not over Rectangle");
var newYPosText = document.createTextNode("Y Position : Not over Rectangle");
targetXtext.replaceChild(newXPosText,targetXtext.firstChild);
targetYtext.replaceChild(newYPosText,targetYtext.firstChild);
}
function recordClick(evt){
targetClickText=document.getElementById("ClickPos");
var XPos = evt.clientX;
var YPos = evt.clientY;
var newClickText =document.createTextNode("Last Click made at X=" + XPos + " Y=" + YPos);
targetClickText.replaceChild(newClickText,targetClickText.firstChild);
}
]]>
</script>
<text id="XPos" x="50" y="50">X Position :</text>
<text id="YPos" x="50" y="70">Y Position :</text>
<text id="ClickPos" x="50" y="90">Last Click made at : </text>
<rect x="50" y="100" width="200" height="200" style="fill:blue" onmousemove="changeText(evt)" onmouseout="changeTextNotOver(evt)" onclick="recordClick(evt)"/>
</svg>
将鼠标移动到矩形上面时,会显示鼠标的 X 和 Y 位置,并且这两个显示的值会随着鼠标的移动而改变,在矩形上单击鼠标会记录下单击的位置。
分析函数 changeText(evt)
可揭示创建交互文本的步骤:
- 为所使用的每一个文本元素指定
id
,这样脚本就可以提取它们。 - 第一次调用
svgDocument.getElementById()
,其中传递的参数是要改变的文本元素的 ID。它被存储在一个变量中以供以后使用。 - 调用
evt
方法getClientX()
和getClientY()
以得到指针的 X 和 Y 坐标,并将它们存储在变量XPos
和YPos
中。 - 调用
svgDocument.createTextNode()
创建一个新文本节点。将更新过的文本字符串传递给这个函数。 - 最后,对这个文字元素调用
replaceChild
方法。它带两个参数 -- 替换文本节点和被替换的子元素。对getFirstChild()
的调用保证更新的文本放置正确。
参照清单7,您应该可以将交互文本加入到自己的 SVG 文档中。
结束语
可以使用本文中描述的各种交互技术使您的 SVG 文档对用户有更大的用途。设法将这些技术结合在一起以得到您想要的功能。
看一下 这个小例子以了解如何综合使用这些技术制作一个交互菜单。
上一篇: PHP:风雨欲来 路在何方?_php基础
下一篇: 从零开始理解JAVA事件处理机制