在 SVG 中包含 JavaScript

发布于 2024-10-25 13:43:24 字数 1642 浏览 1 评论 0原文

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

<?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 一起移动的球,但球没有移动。我做错了什么?

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>

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

对你再特殊 2024-11-01 13:43:24

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

svg {
  height: 178px;
  width: 600px;
  border: solid 1px;
}
<!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="100" 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. 不要依赖全局事件对象;这是老IE的废话。使用传递给事件处理程序的事件对象。

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

  1. 由于您正在修改 xy 变量,因此无需重新获取 cxcy 属性每次按键。

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

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

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

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

  2. 如果您希望它在所有浏览器中工作,请使用 keydown 和我上面提供的 ASCII 事件代码,而不是 keypress 和您使用的奇数。

编辑:您在另一篇文章中抱怨说无法执行此操作,因为您希望在按住该键时重复处理事件处理程序。请注意,您想要的行为是通过我在 Chrome、Safari、Firefox 和 IE 中的示例代码实现的(我没有 Opera 来测试)。换句话说,keydown 按您想要的方式工作,无论您认为它应该如何表现。

编辑 2:如果您想在文档顶部包含一个脚本块,那么在创建所有元素之前,您可以执行如下操作:

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

外部函数将仅运行一次页面已加载,因此您可以确定元素存在以引用它们。

Here is a working version as I would write it:

svg {
  height: 178px;
  width: 600px;
  border: solid 1px;
}
<!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="100" 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>

Some notes:

  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.

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

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.

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

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.

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

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.

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

  2. 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.

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.

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.

放低过去 2024-11-01 13:43:24

您可以通过在 svg 标签中声明 script 标签来将脚本 js 添加到 svg 代码中:

<svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="40px" height="40px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
     ...
  <script type="text/javascript">
        window.addEventListener('load',function(){
        alert('Hi')
        })
    </script>   

</svg>

you can add script js into svg code by declare script tag into svg tag:

<svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="40px" height="40px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
     ...
  <script type="text/javascript">
        window.addEventListener('load',function(){
        alert('Hi')
        })
    </script>   

</svg>
趴在窗边数星星i 2024-11-01 13:43:24

这适用于 Chrome。您遇到了一些错误,例如有时仅对 getElementsByTagName 建立索引。另外一个大问题是 onkeypress 属性没有绑定。

<?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"
>
<script type="text/javascript">
    <![CDATA[

    var x;
    var y;
    function move()
    {
        x = new Number(document.getElementsByTagName("circle")[0].getAttribute("cx"));
        y = new Number (document.getElementsByTagName("circle")[0].getAttribute("cy"));
        switch (event.keyCode)
        {
            case 119:
            y--;
            y = y.toString();
            document.getElementsByTagName("circle")[0].setAttribute("cy",y);
            break;
            case 115:
            y++;
            y = y.toString();
            document.getElementsByTagName("circle")[0].setAttribute("cy",y);
            break;
            case 97:
            x--;
            x = x.toString();
            document.getElementsByTagName("circle")[0].setAttribute("cx",x);
            break;
            case 100:
            x++;
            x = x.toString();
            document.getElementsByTagName("circle")[0].setAttribute("cx",x);
            break;
            default:
        }
    }
    document.documentElement.addEventListener("keypress", move);
    ]]>
</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>

This works in Chrome. You had a few errors, like indexing getElementsByTagName only sometimes. Plus the big problem was that the onkeypress attribute wasn't binding.

<?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"
>
<script type="text/javascript">
    <![CDATA[

    var x;
    var y;
    function move()
    {
        x = new Number(document.getElementsByTagName("circle")[0].getAttribute("cx"));
        y = new Number (document.getElementsByTagName("circle")[0].getAttribute("cy"));
        switch (event.keyCode)
        {
            case 119:
            y--;
            y = y.toString();
            document.getElementsByTagName("circle")[0].setAttribute("cy",y);
            break;
            case 115:
            y++;
            y = y.toString();
            document.getElementsByTagName("circle")[0].setAttribute("cy",y);
            break;
            case 97:
            x--;
            x = x.toString();
            document.getElementsByTagName("circle")[0].setAttribute("cx",x);
            break;
            case 100:
            x++;
            x = x.toString();
            document.getElementsByTagName("circle")[0].setAttribute("cx",x);
            break;
            default:
        }
    }
    document.documentElement.addEventListener("keypress", move);
    ]]>
</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>
倾其所爱 2024-11-01 13:43:24

简单示例

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path d="M90,18c-90-45-115,102,0,69v-21l4-3h-23l-8,4h16v19c-80,15-65-106,2-63l-4,5l4-1z" fill="#CCC" stroke="#DDD" stroke-width="2" stroke-linejoin="round"/>
<path d="M87,15c-90-45-115,102,0,69v-21l4-3h-23l-8,4h16v19c-80,15-65-106,2-63l-4,5l4-1z" fill="#00F"/>
<script>
    alert("Hello world");
</script>
</svg>

Simple Example

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path d="M90,18c-90-45-115,102,0,69v-21l4-3h-23l-8,4h16v19c-80,15-65-106,2-63l-4,5l4-1z" fill="#CCC" stroke="#DDD" stroke-width="2" stroke-linejoin="round"/>
<path d="M87,15c-90-45-115,102,0,69v-21l4-3h-23l-8,4h16v19c-80,15-65-106,2-63l-4,5l4-1z" fill="#00F"/>
<script>
    alert("Hello world");
</script>
</svg>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文