`
piperzero
  • 浏览: 3473426 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

在 SVG 中添加交互性

 
阅读更多

简介: 可伸缩矢量图(Scalable Vector Graphics SVG)是一种基于 XML 的语言,用于绘制二维图形。不过,它的能力不局限于简单的静态矢量图形。本文展示了如何将交互元素加入到 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 属性 --如填充颜色、笔划宽度、大小和透明度 -- 都可以以这种方式改变。

文字元素可以对两种事件做出反应 -- mouseovermousedown 。这表明可以对同一个元素指定多个事件。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就变为 onclickmouseover 就变为 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.getTarget();
   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

  1. 编写 SVG 脚本的第一步是通知查看程序不再使用 SVG,而是使用脚本语言。还必须用 type 属性定义使用哪种脚本语言编码。在这里它设置为 text/javascript
  2. <![CDATA[ 是 XML命令,它告诉查看程序停止解析代码,并读取接下来的块中的代码,这里的代码是字符数据的形式。这可以防止查看程序将括号和其他特殊字符按SVG 元素处理,并使脚本编写更容易。
  3. 现在就可以开始脚本了。首先,定义三个变量: redValgreenValblueVal 。这些变量分别具有red、green 和 blue值,它们将在函数中用到。这个函数名为 changeCol ,它带有一个参数 (evt)。evt是一个 SVG 保留字,它描述刚发生的事件。这里, evt 方法称为 getTarget(), 这个方法返回对触发该事件的SVG 对象的一个引用。这个引用被存储在变量 targetShape 中。
  4. 用简单的 JavaScript 函数 Math 生成三个值在 0到 255 之间的随机数。
  5. 最后,对 targetshape 调用 setAttribute 方法。用前一步中生成的三个随机数将该对象的 fill 属性设置为一个 RGB 值(如 rgb(150,200,50) )。
  6. 关闭 CDATA 块和脚本后,返回 SVG。画出一个圆,通过 onClick 元素,在单击时让它调用函数 changeCol(evt)。

单击这里以便观看效果。单击这个圆时,每次单击它时填充都会变为一个随机颜色。

当一个函数要应用到多个 SVG元素时,脚本是最有用的。例如,可以在清单6中添加一个矩形,如下所示:

    <rect x="400" cy="400" width="100" height="100" fill="blue" 
          onclick="changeCol(evt)" /> 


单击时,这个矩形会与前面的圆形一样调用同一个脚本改变其颜色。

要查看这一点,可以看一下 其他例子。如果查看源代码,您会看到三个方法: changeColchangeEdgeresetEdge 。试着将鼠标移动矩形上面并单击。所有矩形都设置为响应 onclickonmouseoveronmouseout 事件,它们为此调用的是同一个脚本函数。还要注意 onload属性:第一次装载 SVG 文档时要调用这个属性,它对于您的 SVG初始化很有用。

交互文本

在 SVG 中创建交互文本比您想象中的要复杂一些。在定义文本元素时,显示的文本是文本元素的子元素,而不是像 font-size这样的属性,因此不能像前面那样简单地调用 setAttribute来修改其内容。相反,必须创建一个新的文本元素,并用它替换当前的文本元素。清单7展示了一个例子。


清单7. 编写文本变化的脚本

 
<svg> 
<script type="text/javascript">
<![CDATA[
function changeText(evt)
{
   targetXtext=svgDocument.getElementById("XPos");
   targetYtext=svgDocument.getElementById("YPos");
   var XPos = evt.getClientX();
   var YPos = evt.getClientY();
   var newXPosText = svgDocument.createTextNode("X Position : " + XPos);
   var newYPosText = svgDocument.createTextNode("Y Position : " + YPos);
   targetXtext.replaceChild(newXPosText,targetXtext.getFirstChild());
   targetYtext.replaceChild(newYPosText,targetYtext.getFirstChild());
}
function changeTextNotOver(evt)
{
   targetXtext=svgDocument.getElementById("XPos");
   targetYtext=svgDocument.getElementById("YPos");
   var newXPosText = 
     svgDocument.createTextNode("X Position : Not over Rectangle");
   var newYPosText = 
     svgDocument.createTextNode("Y Position : Not over Rectangle");
   targetXtext.replaceChild(newXPosText,targetXtext.getFirstChild());
   targetYtext.replaceChild(newYPosText,targetYtext.getFirstChild());
}
function recordClick(evt)
{
   targetClickText=svgDocument.getElementById("ClickPos");
   var XPos = evt.getClientX();
   var YPos = evt.getClientY();
   var newClickText = 
     svgDocument.createTextNode("Last Click made at X=" + XPos + " Y=" + YPos);
   targetClickText.replaceChild(newClickText, 
         targetClickText.getFirstChild());
}
// ]]>
</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) 可揭示创建交互文本的步骤:

  1. 为所使用的每一个文本元素指定 id ,这样脚本就可以提取它们。
  2. 第一次调用 svgDocument.getElementById() ,其中传递的参数是要改变的文本元素的ID。它被存储在一个变量中以供以后使用。
  3. 调用 evt 方法 getClientX()getClientY()以得到指针的 X 和 Y 坐标,并将它们存储在变量 XPosYPos 中。
  4. 调用 svgDocument.createTextNode() 创建一个新文本节点。将更新过的文本字符串传递给这个函数。
  5. 最后,对这个文字元素调用 replaceChild方法。它带两个参数 --替换文本节点和被替换的子元素。对 getFirstChild() 的调用保证更新的文本放置正确。

参照清单7,您应该可以将交互文本加入到自己的 SVG 文档中。


结束语

可以使用本文中描述的各种交互技术使您的 SVG文档对用户有更大的用途。设法将这些技术结合在一起以得到您想要的功能。

看一下 这个小例子以了解如何综合使用这些技术制作一个交互菜单。


参考资料

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics