【问题标题】:Call svg javascript function inside html javascript function在 html javascript 函数中调用 svg javascript 函数
【发布时间】:2012-09-28 20:26:57
【问题描述】:

我有一个 SVG 文档,其中绘制了三个圆圈:

<?xml version="1.0"?>
<svg width="450" height="80" xmlns="http://www.w3.org/2000/svg">
    <script>
    document.fillCircle = function(id) {
        var circles = document.getElementsByTagName('circle'),
            circle  = document.getElementById(id);

        [].forEach.call(circles, function(circle) {
            circle.setAttribute('fill','#ffffff');
        });

        circle.setAttribute('fill', '#000000');
    }
    </script>
    <g>
        <line y1="35" x1="35" y2="35" x2="375" stroke-width="3" stroke="#000000"/>
        <circle id="state1" r="30" cy="35" cx="35"  stroke-width="3" stroke="#000000" fill="#ffffff" onclick="fillCircle(this.id);"/>
        <circle id="state2" r="30" cy="35" cx="205" stroke-width="3" stroke="#000000" fill="#ffffff" onclick="fillCircle(this.id);"/>
        <circle id="state3" r="30" cy="35" cx="375" stroke-width="3" stroke="#000000" fill="#ffffff" onclick="fillCircle(this.id);"/>
    </g>
</svg>

出于测试目的,我有 onclick="" 方法,但实际上这个文档是我的 html 文档中的一个对象:

<object id="test" data="test-vector.svg" width="100px" height="100px"></object>

我有一个数据集,这三个圆圈显示了每个项目的“进度”。我通过从服务器中提取新列表来定期更新 JSON 集。对于每个更改的项目,我都想更新实心圆圈。

我想根据一些 javascript 更新 svg。但是,我无法进入 SVG 的 DOM。我真的不在乎 fillCircle() 是否在 svg 中,是否必须使用 &lt;embed&gt;&lt;object&gt; 或其他东西,但这种 javascript 对我不起作用。

<html>
<body>
    <object id="test" data="test-vector.svg"></object>
    <script>
        var svg = document.getElementById('test');
        console.log(svg);
        svg.fillCircle('state2');
    </script>
</body>
</html>

我尝试了一些我在 SO 上找到的东西,例如 this onethis one,但无论我测试什么,异常总是:

Uncaught TypeError: Object #<HTMLObjectElement> has no method 'fillCircle'

【问题讨论】:

    标签: javascript html dom svg


    【解决方案1】:

    为什么不将 SVG 直接嵌入到 HTML 代码中(使用 SVG 标签)? According to W3,这适用于所有现代浏览器(和 IE >= 9)。用 JS 访问和更改圆圈的属性就很简单了……

    <html>
        <body>
            <svg>...</svg>
        </body>
    </html>
    


    如果您想保留 HTML/SVG 结构,可以执行以下操作:

    var svg = document.getElementById("test");
    svg.onload = function(){
        svg.contentDocument.fillCircle("state2");
    };
    

    诀窍是等待 SVG 对象加载(onload 事件);直到那时你才能安全地使用contentDocument 属性。顺便说一句,这也被描述为in this solution on SO(您发布了指向它的链接)。 ;)

    【讨论】:

    • 我不想将 svg 嵌入到我的文档中,因为我需要将其放置在那里大约 30-40 次。我更喜欢将它放在一个文档中,然后将其嵌入所有这些 30-40 次。关于加载,我显然错过了那个答案的重点。我想出了contentDocument 的用法,但也没有失败的负载。 @robert-longson 的回答稍早一些,但感谢您的精彩解释! :)
    【解决方案2】:

    var object = document.getElementById("test") 将为您获取对象元素,但在对象加载之前您不能调用它。一旦你有了它,你就可以使用 object.contentDocument 来处理嵌入的 svg 文档。

    <html>
    <body>
        <object id="test" data="test-vector.svg" onload="f()" ></object>
        <script>
            function f() {
                var svg = document.getElementById('test');
                svg.contentDocument.fillCircle('state2');
            }
        </script>
    </body>
    </html>
    

    【讨论】:

    • 显然我没有想到对象的负载。感谢您的信息。由于个人喜好,我不喜欢onload="f(),但是您为我指明了正确的方向!感谢快速回答!
    • @robert 从一个小实验来看,如果 SVG 的脚本是导入的而不是嵌入的,即如果 fillCircle 在 SVG 导入的外部 js 文件中,这似乎不起作用。这是预期的行为还是有其他方法?
    • @DavidSmith 你应该单独提出一个问题。
    • @robert 谢谢,做到了:stackoverflow.com/questions/45854847/…
    猜你喜欢
    • 2023-03-09
    • 1970-01-01
    • 2020-05-24
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-19
    相关资源
    最近更新 更多