在SVG中包含JavaScript [英] Including JavaScript in SVG

查看:132
本文介绍了在SVG中包含JavaScript的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过在JavaScript中嵌入JavaScript来使用JavaScript创建交互式SVG代码。我不知道这是否是正确的方法:

I am trying to create an interactive SVG code with JavaScript, by embedding the JavaScript in the SVG. I don't know if this is the right way to do this:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg"
onkeypress="move()">
<script type="text/javascript">
    <![CDATA[
    var x;
    var y;
    function move()
    {
        x = new Number(svg.getElementsByTagName("circle")[0].getAttribute("cx"));
        y = new Number (svg.getElementsByTagName("circle")[0].getAttribute("cy"));
        switch (event.keyCode)
        {
            case 119:
            y--;
            y = y.toString();
            svg.getElementsByTagName("circle").setAttribute("cy",y);
            break;
            case 115:
            y++;
            y = y.toString();
            svg.getElementsByTagName("circle").setAttribute("cy",y);
            break;
            case 97:
            x--;
            x = x.toString();
            svg.getElementsByTagName("circle").setAttribute("cx",x);
            break;
            case 100:
            x++;
            x = x.toString();
            svg.getElementsByTagName("circle").setAttribute("cx",x);
            break;
            default:
        }
    }
    ]]>
</script>
<rect x="0" y="0" height="500" width="500" style="stroke-width:1; stroke:black; fill:white"></rect>
<circle cx="250" cy="250" r="50" stroke="red" stroke-width="1" fill="red"></circle>
</svg>

它应该有一个与wasd一起移动的球,但球不会移动。我做错了什么?

It is supposed to have a ball that moves with wasd, but the ball doesn't move. What am I doing wrong?

推荐答案

这是我写的一个工作版本:

Here is a working version as I would write it:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <circle cx="250" cy="250" r="50" fill="red" />
  <script type="text/javascript"><![CDATA[
    var KEY = { w:87, a:65, s:83, d:68 };
    var moveSpeed = 5;
    var circle = document.getElementsByTagName("circle")[0];
    var x = circle.getAttribute('cx')*1,
        y = circle.getAttribute('cy')*1;
    document.documentElement.addEventListener('keydown',function(evt){
      switch (evt.keyCode){
        case KEY.w:
          circle.setAttribute('cy',y-=moveSpeed);
          // Alternatively:
          // circle.cy.baseVal.value = (y-=moveSpeed);
        break;
        case KEY.s:
          circle.setAttribute('cy',y+=moveSpeed);
        break;
        case KEY.a:
          circle.setAttribute('cx',x-=moveSpeed);
        break;
        case KEY.d:
          circle.setAttribute('cx',x+=moveSpeed);
        break;
      }
    },false);
  ]]></script>
</svg>

一些注释:


  1. 不要一次又一次地重新获得对圆圈的引用。使您的代码 DRY 使其更加强大,减少打字,并且(在这种情况下)更快要执行。

  1. Don't re-get the reference to the circle again and again. Making your code DRY makes it more robust, less typing, and (in this case) faster to execute.

编辑:如果根据上面的代码您无法弄清楚如何执行此操作,请发布任何不适合您的代码。

Edit: If you cannot figure out how to do this given my code above, post any code that is not working for you.

不要依赖全局事件对象;这是旧的IE废话。使用传递给事件处理程序的事件对象。

Don't rely on a global event object; that's old IE nonsense. Use the event object passed to your event handler.

编辑:如果引用事件在您的代码中没有参数或该名称的局部变量,您假设将有一个全局事件对象集。相反,请参阅我为您编写的代码,该代码显示事件处理程序传递了一个事件对象。通过给出一个名称,例如我给它命名为 evt ,您将收到一个特定于您的事件处理程序的事件对象。

Edit: If you reference event in your code with no parameter or local variable by that name, you are assuming that there will be a global event object set. Instead, see the code I wrote for you, which shows that the event handler is passed an event object. By giving that a name, such as I gave it the name evt, you are receiving an event object specific to your event handler.

由于您要修改 x y 变量,因此无需重新每次按键都会获得 cx cy 属性。

Since you are modifying the x and y variables, there's no need to re-get the cx and cy attributes each key press.

编辑:在原始代码和您接受的答案中,您声明了 var x 在事件处理程序之外,并且在事件处理程序的开头有 x = ... ,然后 x ++ 在其中一个事件处理程序中。您可以每次重新获取 x 的当前值(正如您所做的那样),然后 setAttribute(...,x + 1),或者(就像我一样)你只能在事件处理程序之前获取属性一次的值,然后在每次处理键事件时假设这个值是正确的。

Edit: In your original code and the answer you accepted, you have declared var x outside your event handler, and you have x = ... at the start of your event handler, and then x++ in one of the event handlers. You can either re-get the current value of x each time (as you did) and then setAttribute(...,x+1), or (as I did) you can only fetch the value of the attribute once before the event handlers and then assume that this value is correct each time you handle the key event.

不要将JavaScript事件处理程序放在元素上,以编程方式附加它们。

Don't put your JavaScript event handlers on your elements, attach them programmatically.

编辑:在您的SVG标记中,您有:< svg ... onkeypress =move()> 。将您的行为与标记混合在HTML中是一个非常糟糕的主意,而SVG中的一个坏主意。而不是使用 onfoo =...属性来描述在元素上发生事件时应该发生什么,而是使用 addEventListner()通过代码附加事件处理程序,而无需编辑SVG标记。

Edit: In your SVG markup you have: <svg ... onkeypress="move()">. Mixing your behavior with your markup is a really bad idea in HTML, and a bad idea in SVG. Instead of using onfoo="..." attributes to describe what should happen when an event occurs on an element, instead use addEventListner() to attach the event handlers via code, without editing your SVG markup.

在将数字设置为字符串之前,无需将数字强制转换为字符串属性。

There's no need to coerce the numbers to strings before setting them as attributes.

使用 keydown 和我上面提供的ASCII事件代码而不是 keypress 以及您希望它在所有浏览器中使用的奇数。

Use keydown and the ASCII event codes I supplied above instead of keypress and the odd numbers you were using if you want it to work in all browsers.

编辑:您在其他帖子中抱怨您无法执行此操作,因为您需要事件处理程序按住键时反复处理。请注意,我在Chrome,Safari,Firefox和IE中的示例代码可以实现您想要的行为(我没有要测试的Opera)。换句话说, keydown 可以按照您的想法运行,不管您认为它应该如何表现。

Edit: You complained in another post that you cannot do this because you want the event handler to be processed repeatedly as the key is held down. Note that your desired behavior is achieved with my sample code in Chrome, Safari, Firefox, and IE (I don't have Opera to test). In other words keydown works as you wanted, despite how you thought it should behave.

编辑2 :如果要在文档顶部包含脚本块,则必须先创建所有元素,然后执行以下操作:

Edit 2: If you want to include a script block at the top of your document, before all elements have necessarily been created, you can do something like the following:

<svg ...>
  <script type="text/javascript">
    window.addEventListener('load',function(){
      var circle = ...;
      document.rootElement.addEventListener('keydown',function(evt){
        ...
      },false);
    },false);
  </script>
  ...
</svg>

外部函数只会在页面加载后运行,因此您可以确保元素存在引用它们。

The outer function will only run once the page has loaded, so you can be sure that the elements exist to reference them.

这篇关于在SVG中包含JavaScript的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆