javascript - 从 SVG 文件调用 JavaScript 函数

标签 javascript html d3.js svg

我有一个 SVG 文件和一个 JavaScript 文件。

在我的 SVG 文件中,我有一些代码,但我想知道的是这少量代码:

<g id="zoomButton">
    <g onclick="zoom()" transform="scale(x,y)">
         <rect x="640" y="20" width="140" height="40"
               style="fill:white;stroke:red;stroke-width:2" />
         <text x="710" y="49"
               style="fill:red;font-size:25px;text-anchor:middle">Zoom</text>
    </g>
</g>

你看我想要这个函数 zoom()单击此按钮时调用。

现在,在我的 JavaScript 文件中,我有一个名为 zoom() 的函数。 :

function zoom() {
    alert("heyho");
}

但是,当我按下 SVG 文件中创建的按钮时,不会触发此功能。我只收到错误消息:

Uncaught ReferenceError: zoom is not defined

我只是希望能够在按下此按钮时调用该 JavaScript 函数。

此外,由于这毕竟是一个缩放功能,并且我想做一些缩放,所以如何访问 transform="scale(x,y) 中的 x 和 y在 zoomButton来自 JavaScript 文件的 SVG 文件?

编辑:

SVG文件中的完整代码如下(game.svg):

<?xml version="1.0" encoding="utf-8"?>
<svg width="800px" height="600px"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xhtml="http://www.w3.org/1999/xhtml"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     xmlns:a="http://www.adobe.com/svg10-extensions" a:timeline="independent"
     onload="top.load(evt)">

  <defs>
    <clipPath id="gameareaclip">
      <rect x="20" y="20" width="600" height="560"/>
    </clipPath>
    <pattern id="background_pattern" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
      <rect width="20" height="20" style="fill:purple"/>
      <circle cx="10" cy="10" r="8" style="fill:black"/>
    </pattern>
    <radialGradient id="player_color">
      <stop offset="0.0" style="stop-color:yellow;stop-opacity:1"/>
      <stop offset="0.8" style="stop-color:yellow;stop-opacity:1"/>
      <stop offset="1.0" style="stop-color:orange;stop-opacity:1"/>
    </radialGradient>
  </defs>

  <rect width="100%" height="100%" style="fill:url(#background_pattern);stroke:orange;stroke-width:4" />

  <rect x="20" y="20" width="600" height="560" style="fill:black;stroke:red;stroke-width:5" />

  <!-- Add your button here -->

  <g id="zoomKnapp">
  <g onclick="zoom()" transform="scale(x,y)">
    <rect x="640" y="20" width="140" height="40"
          style="fill:white;stroke:red;stroke-width:2" />
    <text x="710" y="49"
          style="fill:red;font-size:25px;text-anchor:middle">Zoom</text>
  </g>
</g>

  <g style="clip-path:url(#gameareaclip)">
    <g transform="translate(20,20)">
      <g id="gamearea" transform="translate(0,0)" width="600" height="560">
        <rect x="0" y="0" width="600" height="560" style="fill:lightgrey" />

        <g id="platforms">

          <!-- Add your platforms here -->

  <rect id="svg_37" height="20" width="300" y="100" x="0" stroke-linecap="null" stroke-linejoin="null" stroke-width="0" stroke="#000000" fill="#5fbf00"/>
  <rect id="svg_38" height="20" width="300" y="170" x="300" stroke-linecap="null" stroke-linejoin="null" stroke-width="0" stroke="#000000" fill="#5fbf00"/>
  <rect id="svg_39" height="20" width="300" y="240" x="0" stroke-linecap="null" stroke-linejoin="null" stroke-width="0" stroke="#000000" fill="#5fbf00"/>
  <rect id="svg_40" height="20" width="300" y="310" x="300" stroke-linecap="null" stroke-linejoin="null" stroke-width="0" stroke="#000000" fill="#5fbf00"/>
  <rect id="svg_41" height="20" width="300" y="380" x="0" stroke-linecap="null" stroke-linejoin="null" stroke-width="0" stroke="#000000" fill="#5fbf00"/>
  <rect id="svg_42" height="20" width="300" y="450" x="300" stroke-linecap="null" stroke-linejoin="null" stroke-width="0" stroke="#000000" fill="#5fbf00"/>

        </g>

        <g id="player">
          <circle cx="20" cy="20" r="20" style="fill:url(#player_color);stroke:black;stroke-width:2"/>
          <ellipse cx="15" cy="15" rx="3" ry="6" style="fill:black"/>
          <ellipse cx="25" cy="15" rx="3" ry="6" style="fill:black"/>
          <path d="M10,25 l20,0 q0,8 -10,8 t-10,-8" style="fill:orange;stroke:black;stroke-black:2"/>
        </g>
      </g>
    </g>
  </g>
</svg>

HTML 文件 (game.html):

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>SVG Game</title>
  <script language="JavaScript" src="game.js"></script>
</head>

<body style="text-align: center">
    <embed src="game.svg" type="image/svg+xml" width="800" height="600" />
</body>

</html>

JavaScript (game.js) 代码:

// The point and size class used in this program
function Point(x, y) {
    this.x = (x)? parseFloat(x) : 0.0;
    this.y = (y)? parseFloat(y) : 0.0;
}

function Size(w, h) {
    this.w = (w)? parseFloat(w) : 0.0;
    this.h = (h)? parseFloat(h) : 0.0;
}

// Helper function for checking intersection between two rectangles
function intersect(pos1, size1, pos2, size2) {
    return (pos1.x < pos2.x + size2.w && pos1.x + size1.w > pos2.x &&
            pos1.y < pos2.y + size2.h && pos1.y + size1.h > pos2.y);
}


function zoom() {
    alert("heiho");
}

// The player class used in this program
function Player() {
    this.node = svgdoc.getElementById("player");
    this.position = PLAYER_INIT_POS;
    this.motion = motionType.NONE;
    this.verticalSpeed = 0;
}

Player.prototype.isOnPlatform = function() {
    var platforms = svgdoc.getElementById("platforms");
    for (var i = 0; i < platforms.childNodes.length; i++) {
        var node = platforms.childNodes.item(i);
        if (node.nodeName != "rect") continue;

        var x = parseFloat(node.getAttribute("x"));
        var y = parseFloat(node.getAttribute("y"));
        var w = parseFloat(node.getAttribute("width"));
        var h = parseFloat(node.getAttribute("height"));

        if (((this.position.x + PLAYER_SIZE.w > x && this.position.x < x + w) ||
             ((this.position.x + PLAYER_SIZE.w) == x && this.motion == motionType.RIGHT) ||
             (this.position.x == (x + w) && this.motion == motionType.LEFT)) &&
            this.position.y + PLAYER_SIZE.h == y) return true;
    }
    if (this.position.y + PLAYER_SIZE.h == SCREEN_SIZE.h) return true;

    return false;
}

Player.prototype.collidePlatform = function(position) {
    var platforms = svgdoc.getElementById("platforms");
    for (var i = 0; i < platforms.childNodes.length; i++) {
        var node = platforms.childNodes.item(i);
        if (node.nodeName != "rect") continue;

        var x = parseFloat(node.getAttribute("x"));
        var y = parseFloat(node.getAttribute("y"));
        var w = parseFloat(node.getAttribute("width"));
        var h = parseFloat(node.getAttribute("height"));
        var pos = new Point(x, y);
        var size = new Size(w, h);

        if (intersect(position, PLAYER_SIZE, pos, size)) {
            position.x = this.position.x;
            if (intersect(position, PLAYER_SIZE, pos, size)) {
                if (this.position.y >= y + h)
                    position.y = y + h;
                else
                    position.y = y - PLAYER_SIZE.h;
                this.verticalSpeed = 0;
            }
        }
    }
}

Player.prototype.collideScreen = function(position) {
    if (position.x < 0) position.x = 0;
    if (position.x + PLAYER_SIZE.w > SCREEN_SIZE.w) position.x = SCREEN_SIZE.w - PLAYER_SIZE.w;
    if (position.y < 0) {
        position.y = 0;
        this.verticalSpeed = 0;
    }
    if (position.y + PLAYER_SIZE.h > SCREEN_SIZE.h) {
        position.y = SCREEN_SIZE.h - PLAYER_SIZE.h;
        this.verticalSpeed = 0;
    }
}


//
// Below are constants used in the game
//
var PLAYER_SIZE = new Size(40, 40);         // The size of the player
var SCREEN_SIZE = new Size(600, 560);       // The size of the game screen
var PLAYER_INIT_POS  = new Point(0, 0);     // The initial position of the player

var MOVE_DISPLACEMENT = 5;                  // The speed of the player in motion
var JUMP_SPEED = 15;                        // The speed of the player jumping
var VERTICAL_DISPLACEMENT = 1;              // The displacement of vertical speed

var GAME_INTERVAL = 25;                     // The time interval of running the game


//
// Variables in the game
//
var motionType = {NONE:0, LEFT:1, RIGHT:2}; // Motion enum

var svgdoc = null;                          // SVG root document node
var player = null;                          // The player object
var gameInterval = null;                    // The interval
var zoom = 1.0;                             // The zoom level of the screen


//
// The load function for the SVG document
//
function load(evt) {
    // Set the root node to the global variable
    svgdoc = evt.target.ownerDocument;

    // Attach keyboard events
    svgdoc.documentElement.addEventListener("keydown", keydown, false);
    svgdoc.documentElement.addEventListener("keyup", keyup, false);

    // Remove text nodes in the 'platforms' group
    cleanUpGroup("platforms", true);

    // Create the player
    player = new Player();

    // Start the game interval
    gameInterval = setInterval("gamePlay()", GAME_INTERVAL);
}


//
// This function removes all/certain nodes under a group
//
function cleanUpGroup(id, textOnly) {
    var node, next;
    var group = svgdoc.getElementById(id);
    node = group.firstChild;
    while (node != null) {
        next = node.nextSibling;
        if (!textOnly || node.nodeType == 3) // A text node
            group.removeChild(node);
        node = next;
    }
}


//
// This is the keydown handling function for the SVG document
//
function keydown(evt) {
    var keyCode = (evt.keyCode)? evt.keyCode : evt.getKeyCode();

    switch (keyCode) {
        case "N".charCodeAt(0):
            player.motion = motionType.LEFT;
            break;

        case "M".charCodeAt(0):
            player.motion = motionType.RIGHT;
            break;


        // Add your code here
        case "Z".charCodeAt(0):
        if (player.isOnPlatform()) {
          //Jump
          player.verticalSpeed = JUMP_SPEED;
        }
            break;


    }
}


//
// This is the keyup handling function for the SVG document
//
function keyup(evt) {
    // Get the key code
    var keyCode = (evt.keyCode)? evt.keyCode : evt.getKeyCode();

    switch (keyCode) {
        case "N".charCodeAt(0):
            if (player.motion == motionType.LEFT) player.motion = motionType.NONE;
            break;

        case "M".charCodeAt(0):
            if (player.motion == motionType.RIGHT) player.motion = motionType.NONE;
            break;
    }
}


//
// This function updates the position and motion of the player in the system
//
function gamePlay() {
    // Check whether the player is on a platform
    var isOnPlatform = player.isOnPlatform();

    // Update player position
    var displacement = new Point();

    // Move left or right
    if (player.motion == motionType.LEFT)
        displacement.x = -MOVE_DISPLACEMENT;
    if (player.motion == motionType.RIGHT)
        displacement.x = MOVE_DISPLACEMENT;

    // Fall
    if (!isOnPlatform && player.verticalSpeed <= 0) {
        displacement.y = -player.verticalSpeed;
        player.verticalSpeed -= VERTICAL_DISPLACEMENT;
    }

    // Jump
    if (player.verticalSpeed > 0) {
        displacement.y = -player.verticalSpeed;
        player.verticalSpeed -= VERTICAL_DISPLACEMENT;
        if (player.verticalSpeed <= 0)
            player.verticalSpeed = 0;
    }

    // Get the new position of the player
    var position = new Point();
    position.x = player.position.x + displacement.x;
    position.y = player.position.y + displacement.y;

    // Check collision with platforms and screen
    player.collidePlatform(position);
    player.collideScreen(position);

    // Set the location back to the player object (before update the screen)
    player.position = position;

    updateScreen();
}


//
// This function updates the position of the player's SVG object and
// set the appropriate translation of the game screen relative to the
// the position of the player
//
function updateScreen() {
    // Transform the player
    player.node.setAttribute("transform", "translate(" + player.position.x + "," + player.position.y + ")");

    // Calculate the scaling and translation factors

    // Add your code here

}

最佳答案

脚本标签需要位于 SVG 文件 (game.svg) 中,而不是位于 html 文件中。请注意SVG script标签使用 xlink:href 而不是 src 作为保存脚本源的属性。

 <script xlink:href="game.js"></script>

您还应该更改onload="top.load(evt)"到只是onload="load(evt)"在根<svg>元素。

第三个也是主要问题是第 114 行有一个函数 Zoom() 和一个名为 Zoom 的变量。删除该变量,因为它没有被使用,并且 Zoom 方法将被调用。

关于javascript - 从 SVG 文件调用 JavaScript 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33051786/

相关文章:

javascript - 获取属性 HTMLDocument.body 的权限被拒绝

javascript - 在 for 循环的初始化表达式中声明的变量是否总是词法在体内

html - 覆盖特定宽度的媒体查询 - CSS

html - 制作重叠按钮

html - 在另一个跨度之前和之后设置跨度位置

javascript - D3.js 交互式图例切换

javascript - 在 D3 中调整圆形 SVG 的大小

javascript - d3.js 强制可折叠图 - 输入数据是对象数组

javascript - 如何在更新增益之前清空状态中的数组?

javascript - 如何将多个外部监听器注册到 d3 中的同一选择?