使用鼠标移动动态创建的 SVG
Move dynamically created SVG with mouse
我对 HTML 和 JS 还很陌生,但我正在努力学习一些基础知识。现在我正在试验图形。
我正在尝试用 JS 动态创建两个 svg 元素,然后用鼠标单独移动它们。
我能够创建它们,并分别在它们上注册鼠标事件,但无法让它们移动。
为了尝试移动到那里的位置,在我的 dragging() 函数中,我将 svg style.top 和 style.left 分配给指针的值。我可以在 JS 控制台中确认该事件是从 SGV 发送的,并且元素标签中的顶部和左侧样式正在发生变化,但屏幕上的位置没有发生变化。
我遵循了另一个示例,其中 svg 通过鼠标分配样式顶部和鼠标值左侧移动,所以我不确定为什么这不起作用。
谢谢
<?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>
几点观察:
您的代码是正确的,但是它非常冗长,所以我需要减少它。
在代码中,您将找到一个从对象创建 SVG 元素的函数。我正在使用此函数创建 svg 元素和圆圈。
我还把 SVG 元素放在一个数组中。当您将相似元素放在数组中时,使用它们更容易。
主要思想是:
svg 元素有 position:absolute
。可以使用 css
中的 top
和 left
属性设置 svg 的位置
鼠标向下拖动为真。如果拖动为真,您可以拖动 svg 元素。 svg 的新位置(它是 top
和 left
属性)根据鼠标位置和鼠标与左上角之间的距离 delta
在 css 中设置SVG 元素的角。
鼠标向上拖动是错误的。 svg元素不能再拖动了
请阅读代码和评论,如果您不明白,请告诉我。
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>
我对 HTML 和 JS 还很陌生,但我正在努力学习一些基础知识。现在我正在试验图形。
我正在尝试用 JS 动态创建两个 svg 元素,然后用鼠标单独移动它们。
我能够创建它们,并分别在它们上注册鼠标事件,但无法让它们移动。
为了尝试移动到那里的位置,在我的 dragging() 函数中,我将 svg style.top 和 style.left 分配给指针的值。我可以在 JS 控制台中确认该事件是从 SGV 发送的,并且元素标签中的顶部和左侧样式正在发生变化,但屏幕上的位置没有发生变化。
我遵循了另一个示例,其中 svg 通过鼠标分配样式顶部和鼠标值左侧移动,所以我不确定为什么这不起作用。
谢谢
<?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>
几点观察: 您的代码是正确的,但是它非常冗长,所以我需要减少它。 在代码中,您将找到一个从对象创建 SVG 元素的函数。我正在使用此函数创建 svg 元素和圆圈。
我还把 SVG 元素放在一个数组中。当您将相似元素放在数组中时,使用它们更容易。
主要思想是:
svg 元素有
position:absolute
。可以使用 css 中的 鼠标向下拖动为真。如果拖动为真,您可以拖动 svg 元素。 svg 的新位置(它是
top
和left
属性)根据鼠标位置和鼠标与左上角之间的距离delta
在 css 中设置SVG 元素的角。鼠标向上拖动是错误的。 svg元素不能再拖动了
top
和 left
属性设置 svg 的位置
请阅读代码和评论,如果您不明白,请告诉我。
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>