Move dynamically created SVG with mouse

限于喜欢 提交于 2021-02-11 13:53:36

问题


I'm pretty new to HTML and JS, but I'm trying to learn some of the basics. Now I'm experimenting with graphics.
I'm trying to create two svg elements dynamically with JS and then move them individually with the mouse.
I'm able to create them, and register the mouse events on them individually, but can't get them to move. To try to move there positions, in my dragging() function I assign the svg style.top and style.left to the value of the pointer. I can confirm in the JS console that the event is sent from the SGV and that the top and left styles are changing in the element tag, but the position on screen is not changing.
I followed another example where the svg was moved with the mouse assigning style top and left with the mouse values, so I'm not sure why this isn't working.
Thanks

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <title>SVG Test</title>    
</head>
<body>

<h1>Testing <abbr>SVG</abbr></h1>
<div id="svg54583"></div>
<script>     

        // create the svg element
       var svg1 = document.createElementNS("http://www.w3.org/2000/svg", "svg");

        // set width and height
        svg1.setAttribute("width", "100");
        svg1.setAttribute("height", "100");
        svg1.setAttribute("id", "firstsvg");
        svg1.onmousedown = startdrag;

        // create a circle
        var cir1 = document.createElementNS("http://www.w3.org/2000/svg", "circle");
        cir1.setAttribute("cx", "80");
        cir1.setAttribute("cy", "80");
        cir1.setAttribute("r", "30");
        cir1.setAttribute("fill", "red");

        // attach it to the container
        svg1.appendChild(cir1);

        // attach container to document
        //document.getElementById("svg54583").appendChild(svg1);
        document.body.appendChild(svg1);

        var svg1 = document.createElementNS("http://www.w3.org/2000/svg", "svg");

        // set width and height
        svg1.setAttribute("width", "100");
        svg1.setAttribute("height", "100");
        svg1.setAttribute("id", "secondsvg");
        svg1.onmousedown = startdrag;

        // create a circle
        var cir1 = document.createElementNS("http://www.w3.org/2000/svg", "circle");
        cir1.setAttribute("cx", "80");
        cir1.setAttribute("cy", "80");
        cir1.setAttribute("r", "30");
        cir1.setAttribute("fill", "red");

        // attach it to the container
        svg1.appendChild(cir1);

        // attach container to document
        //document.getElementById("svg54583").appendChild(svg1);
        document.body.appendChild(svg1);

        function startdrag(e)
        { 

            var elmnt = e.target;
            elmnt.onmousemove = dragging;   

        }

        function dragging(e)
        {
            var elmnt = e.target;
            elmnt.style.top = e.clientY ;
            elmnt.style.left = e.clientX ;
            console.log(elmnt);
        }    

</script>


回答1:


A few observations: your code is correct, however it's extremely verbose so I needed to reduce it. In the code you'll find a function to create an SVG element from an object. I'm using this function to create the svg elements and the circles.

Also I'm putting the SVG elements in an array. It's easier to wotk with similar elements when you have them in an array.

The main idea is:

  1. The svg elements have position:absolute. The position of the svg can be set using the top and left properties in css

  2. On mouse down drag is true. If drag is true you can drag the svg element. The new position of the svg (it's top and left properties) are set in css in function of the mouse position and the distance delta between the mouse and the top left corner of the SVG element.

  3. On mouse up drag is false. The svg element can't be dragged any longer.

Please read the code and the comments and let me know if you don't understand.

const SVG_NS = "http://www.w3.org/2000/svg";
let svg1 = {
  width: 100,
  height: 100
};

let circle1 = {
  cx: 80,
  cy: 80,
  r: 30,
  fill: "red"
};

let drag = null;// a flag to know if you can drag or not
let _array = [];// the array of scg elements
let delta = {};// distance between the mouse and the top left coener of the SVG element
let m = {};// mouse position

function createSVGElement(o, elmtName, parent) {
  var elmt = document.createElementNS(SVG_NS, elmtName);
  for (var name in o) {
    if (o.hasOwnProperty(name)) {
      elmt.setAttributeNS(null, name, o[name]);
    }
  }
  parent.appendChild(elmt);
  return elmt;
}

let firstsvg = createSVGElement(svg1, "svg", svg54583);
let firstCircle = createSVGElement(circle1, "circle", firstsvg);

let secondsvg = createSVGElement(svg1, "svg", svg54583);
let secondCircle = createSVGElement(circle1, "circle", secondsvg);

_array.push(firstsvg);
_array.push(secondsvg);



_array.forEach((svg, i) => {
  svg.addEventListener("mousedown", evt => {
    // you can drag
    drag = i + 1; // i + 1 because 0 is false. I need it to be true
    let pos = svg.getBoundingClientRect();
    // distance between the mouse and the top left coener of the SVG
    delta.x = evt.clientX - pos.x;
    delta.y = evt.clientY - pos.y;
  });
});

svg54583.addEventListener("mousemove", evt => {
  if (drag) {
    m = oMousePos(svg54583, evt); //console.log("m",m);
    _array[drag - 1].style.left = m.x - delta.x + "px";
    _array[drag - 1].style.top = m.y - delta.y + "px";
  }
});

svg54583.addEventListener("mouseup", evt => {
  drag = null;
});

function oMousePos(elmt, evt) {
  var ClientRect = elmt.getBoundingClientRect();
  return {
    //objeto
    x: Math.round(evt.clientX - ClientRect.left),
    y: Math.round(evt.clientY - ClientRect.top)
  };
}
*{margin:0;padding:0;}
svg{border:1px solid; position:absolute;background:white;}

svg:nth-of-type(2){left:200px;}

#svg54583{width:100vw; height:100vh; background:lightGrey; border:1px solid;}
<div id="svg54583"></div>


来源:https://stackoverflow.com/questions/54158088/move-dynamically-created-svg-with-mouse

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!