【问题标题】:identify dynamically created svg element识别动态创建的 svg 元素
【发布时间】:2015-07-09 09:36:21
【问题描述】:

我正在尝试操作svg 中的元素(例如圆圈或路径)。我需要动态创建它们并能够识别它们。

我从一些在线示例中窃取了一些功能,并提出了以下代码(它应该在鼠标单击时在 svg 内创建圆圈,当鼠标悬停在圆圈上时会创建一个文本标签)。但是,它没有按我的预期工作。当鼠标从左边进入元素时,elementFromPoint(x, y).id 返回 valid ID "circle",但是当鼠标从右边进入元素时,它返回它的父 ID“mySVG”。

我无法在任何地方找到合适的解决方案,因此欢迎任何建议 - 事实上,我会尝试阅读 svg 的规范并尽可能地学习 JS,但是,这对我来说仍然是一个痛苦的过程去理解这些东西。非常感谢您的时间和建议!谢谢。 k

JS 小提琴:

https://jsfiddle.net/krisfiddle/2xc3tgdr/6/

代码

<!doctype html>
<html>

    <head>
    <meta charset="utf-8">
    <title></title>

    <style>
        body, canvas, svg {position:absolute; margin:0; padding:0; border:none;}

        svg {top:0; left:0;}

        .circle:hover {opacity:0.5;}

    </style>

    </head>

    <body>
    <svg id="mySVG" xmlns:xlink="http://www.w3.org/1999/xlink" height="400" width="300" style="border: 1px solid black" onClick="circle()"></svg>

    <script>
        var w = window.innerWidth;
        var h = window.innerHeight;
        var x;
        var y;
        var color = undefined;

       function handleMouseMove(event) {
            var dot, eventDoc, doc, body, pageX, pageY;

            event = event || window.event;

            if (event.pageX == null && event.clientX != null) {
                eventDoc = (event.target && event.target.ownerDocument) || document;
                doc = eventDoc.documentElement;
                body = eventDoc.body;

                event.pageX = event.clientX +
                  (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
                  (doc && doc.clientLeft || body && body.clientLeft || 0);
                event.pageY = event.clientY +
                  (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
                  (doc && doc.clientTop  || body && body.clientTop  || 0 );
            }

            x = event.pageX;
            y = event.pageY;
            }
        document.onmousemove = handleMouseMove;

        function circle() {
            var myCircle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
            myCircle.setAttribute('id', 'circleID');
            myCircle.setAttribute('class', 'circle');
            myCircle.setAttributeNS(null, "cx", x);
            myCircle.setAttributeNS(null, "cy", y);
            myCircle.setAttributeNS(null, "r", 50);
            myCircle.setAttributeNS(null, "fill", "green");
            myCircle.setAttributeNS(null, "stroke", "none");
            myCircle.setAttributeNS(null, "onmouseover", "getIdXY()");
            myCircle.setAttributeNS(null, "onmouseout", "deleteIdXY()");
            document.getElementById("mySVG").appendChild(myCircle); 
        }

        function getIdXY() {
        var elementMouseIsOver = document.  
        var idMark = document.createElementNS("http://www.w3.org/2000/svg", "text");
        idMark.setAttributeNS(null, "x", x);
        idMark.setAttributeNS(null, "y", y);
        idMark.setAttributeNS(null, "fill", "red");
        idMark.setAttributeNS(null, "id", "text");
        document.getElementById("mySVG").appendChild(idMark);
        document.getElementById("text").innerHTML = elementMouseIsOver;
        }

        function deleteIdXY() {
            var parent = document.getElementById("mySVG");
            var child = document.getElementById("text");
            parent.removeChild(child);
        }
    </script>

    </body>
    </html>

【问题讨论】:

    标签: javascript svg elements identify


    【解决方案1】:

    问题是你的结构全错了。

    在单击处理程序中获取单击的当前坐标,并在处理程序之外保留某种计数器(但可以访问),每次创建圆时都会递增。这样,您就可以将该号码添加到 circleID。

    【讨论】:

    • 感谢您的指导,我会尽力实现这些。非常感激! k
    【解决方案2】:

    问题在于使用 elementFromPoint(),它可能会返回该位置的任一元素。

    这是一个有趣的问题,因为method reference 表示它应该返回最顶部的元素,即圆圈。然而,这不是观察到的行为,即当鼠标从左侧或右侧进入圆圈时。

    现有代码可用于以下更改。

    // myCircle.setAttributeNS(null, "onmouseover", "getIdXY()");
    
    myCircle.setAttributeNS(null, "onmouseover", "getIdXY(this)");
    
    //function getIdXY() {
        //var elementMouseIsOver = document.elementFromPoint(x, y).id;  
    
    function getIdXY( obj ) {
       var elementMouseIsOver = obj.id;
    

    【讨论】:

    • 我一定会尝试的。谢谢你的建议! k
    • 上面提到的 MozDev 参考说:“如果指定点的元素属于另一个文档(例如,iframe 的子文档),则返回子文档的父元素(iframe 本身)。” -> 这也许可以解释这种行为,不是吗? Svg 在 html 文件中,并且在加载文档后将圆圈添加到 dom 中。对于我没有受过教育的大脑来说,这类似于跨域问题导致 JS 生成的 img 对象被包含在画布中(想想,我不完全理解这类事情)。
    【解决方案3】:

    好吧,我暂时实施了 Robert 和 Marcin 的两个建议。由于某种原因, elementFromPoint() 在这个特定的实现中对我来说似乎很难处理,因此我很高兴转向“this obj”方法。事实上,将坐标存储在全局变量中并为元素分配唯一 ID 是一个好主意。认为代码不是很优雅,它让我很好地介绍了 JS 和动态创建的 SVG。非常感谢 Marcin 和 Robert。目前的结果对我的目的来说是令人满意的,可以在下面的小提琴中观察到:

    http://jsfiddle.net/4uu1vbzz/2/

    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <title></title>
    </head>
    
    <body>
        <svg id="mySVG" xmlns:xlink="http://www.w3.org/1999/xlink" height="400" width="300" style="border: 1px solid black"></svg>    
    </body>
    
    <script>
    var x, y, recentX, recentY; // stores XY mouse coordinations
    var circleID = 0; // used as increment to generate unique ID for each circle
    var tagID = 0; // used as increment to generate unique ID for each circle's tag
    var elementMouseIsOver = ""; // stores ID of the element recently under the pointer
    
    // get mouse coords on mouse move   
    var mouseMoves = function(e) {
        recentX = e.clientX;
        recentY = e.clientY;
        }
        window.onload = function() {this.addEventListener('mousemove', mouseMoves);} //event handler for mousemove coords
    
    //create circle within svg  
    var draw = function draw(e) {
        x = e.clientX; 
        y = e.clientY;
    
        circleID = circleID + 1; //increment the number for ID
        var id = "circle" + circleID; //create string to pass the ID
    
        //place circle with ID into svg
        var myCircle = document.createElementNS("http://www.w3.org/2000/svg", "circle");        
        myCircle.setAttribute('id', id);
        myCircle.setAttribute('class', 'circle');
        myCircle.setAttributeNS(null, "cx", x);
        myCircle.setAttributeNS(null, "cy", y);
        myCircle.setAttributeNS(null, "r", 50);
        myCircle.setAttributeNS(null, "fill", "green");
        myCircle.setAttributeNS(null, "stroke", "none");
        myCircle.setAttributeNS(null, "onmouseover", "tagId(this)");
        myCircle.setAttributeNS(null, "onmouseout", "deleteTag()");
        document.getElementById("mySVG").appendChild(myCircle);
        }
        document.getElementById("mySVG").addEventListener('click', draw); //event handler for onclick action
    
    //on mouseover get the ID of the element under the pointer and create an tag marking it
    function tagId(obj) {
        elementMouseIsOver = obj.id;
        tagID = tagID + 1;
        var id = "tag" + tagID;
        var idMark = document.createElementNS("http://www.w3.org/2000/svg", "text");
        idMark.setAttributeNS(null, "x", recentX);
        idMark.setAttributeNS(null, "y", recentY);
        idMark.setAttributeNS(null, "fill", "red");
        idMark.setAttributeNS(null, "id", id);
        document.getElementById("mySVG").appendChild(idMark);
        document.getElementById(id).innerHTML = elementMouseIsOver;
        }
    
    //remove the tag when mouse leaves the element  
    function deleteTag() {
        var id = "tag" + tagID;
        var parent = document.getElementById("mySVG");
        var child = document.getElementById(id);
        parent.removeChild(child);
        }
    </script>
    </html>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-30
      • 1970-01-01
      相关资源
      最近更新 更多