2

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

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

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

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>
4

3 回答 3

2

好吧,就目前而言,我实施了 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>
于 2015-04-30T22:48:07.093 回答
0

问题是你的结构全错了。

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

于 2015-04-29T21:37:31.247 回答
0

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

这是一个有趣的问题,因为方法参考说它应该返回最顶层的元素,即圆。然而,这不是观察到的行为,即当鼠标从左侧或右侧进入圆圈时。

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

// 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;
于 2015-04-29T23:09:12.147 回答