生成和拖动 SVG 元素 - 方法

     2023-05-08     161

关键词:

【中文标题】生成和拖动 SVG 元素 - 方法【英文标题】:spawn & drag of SVG elements - approach 【发布时间】:2017-03-09 15:51:46 【问题描述】:

我正在学习 Javascript/SVG 组合(动画和制作交互式 SVG)。

我想创建一个代码 sn-p,其中菜单元素(“库存”)可以拖动到主屏幕(“画布”),而原始元素将保留在其位置(就像移动副本一样它脱离了原始元素)。

在这里,我尽我所能编写了代码 sn-p: http://codepen.io/cmer41k/pen/f2b5eea274cdde29b0b2dc8a2424a645

所以我设法做了一些事情,但它有问题:

    我可以处理 1 个副本并使其可拖动,但是我不知道如何处理所有这些生成元素的 ID,这会导致拖动问题

    我不明白如何让它无限期地工作(这样它就可以产生任意数量的可拖动到画布上的圆圈)

    画布中的可拖动元素经常重叠,我无法以它们不重叠的方式附加监听器,以便我拖动的元素上的监听器会“通过”那里的任何其他元素传播;(

问题基本上是 - 有人可以建议我应该将逻辑放入这个 sn-p 以便它不那么麻烦。我很确定我在这里遗漏了一些东西;((例如,它不应该那么难,不是吗?)

HTML:

<body>
<svg id="svg"
  
  
    viewbox="0 0 480 800"
    preserveAspectRatio="xMinYMin meet"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
>
    <rect id="canvasBackground"   x="0" y="0"/>
    <rect id="inventoryBackground"   x="0" y="480"/>


<g id="inventory">
<path id="curve4" class="inventory" d="M60,530 A35,35 0 1,1 60,531" />
<path id="curve3" class="inventory" d="M150,530 A35,35 0 1,1 150,531" />
<path id="curve2" class="inventory" d="M240,530 A35,35 0 1,1 240,531" />
<path id="curve1" class="inventory" d="M330,530 A35,35 0 1,1 330,531" />
</g>

<g id="canvas">
</g>

</svg>
</body>

Javascript:

// define meta objects
var drag = null;

// this stores all "curves"-circles
var curves = ;
var canvas = ;
var inventory = ;

window.onload = function() 

        // creates the curve-circles in the object and at their initial x,y coords
        curves.curve1 = document.getElementById("curve1");
        curves.curve1.x = 0;
        curves.curve1.y = 0;
        curves.curve2 = document.getElementById("curve2");
        curves.curve2.x = 0;
        curves.curve2.y = 0;
        curves.curve3 = document.getElementById("curve3");
        curves.curve3.x = 0;
        curves.curve3.y = 0;
        curves.curve4 = document.getElementById("curve4");
        curves.curve4.x = 0;
        curves.curve4.y = 0;
        canvas = document.getElementById("canvas");
        inventory = document.getElementById("inventory");

        // attach events listeners

        AttachListeners();


function AttachListeners() 
    var ttt = document.getElementsByClassName('inventory'), i;
    for (i = 0; i < ttt.length; i++) 
    document.getElementsByClassName("inventory")[i].onmousedown=Drag;
    document.getElementsByClassName("inventory")[i].onmousemove=Drag;
    document.getElementsByClassName("inventory")[i].onmouseup=Drag;
    


// Drag function that needs to be modified;//
function Drag(e) 
        e.stopPropagation();
        var t = e.target, id = t.id, et = e.type;  m = MousePos(e);

            if (!drag && (et == "mousedown")) 

                if (t.className.baseVal=="inventory")  //if its inventory class item, this should get cloned into draggable?
                    copy = t.cloneNode(true);
                    copy.onmousedown=copy.onmousemove=onmouseup=Drag;
                    inventory.insertBefore(copy, inventory.firstChild);
                    drag = t;
                    dPoint = m;
                 
                if (t.className.baseVal=="draggable")    //if its just draggable class - it can be dragged around
                    drag = t;
                    dPoint = m;
                

            
        // drag the spawned/copied draggable element now
            if (drag && (et == "mousemove")) 
                curves[id].x += m.x - dPoint.x;
                curves[id].y += m.y - dPoint.y;
                dPoint = m;
                curves[id].setAttribute("transform", "translate(" +curves[id].x+","+curves[id].y+")");  
            

        // stop drag
            if (drag && (et == "mouseup")) 
                t.className.baseVal="draggable";
                drag = null;
            




// adjust mouse position to the matrix of SVG & screen size
function MousePos(event) 
        var p = svg.createSVGPoint();
        p.x = event.clientX;
        p.y = event.clientY;
        var matrix = svg.getScreenCTM();
        p = p.matrixTransform(matrix.inverse());
        return 
            x: p.x,
            y: p.y
        

【问题讨论】:

【参考方案1】:

你很亲密。你有几个错误。例如。

copy.onmousedown=copy.onmousemove=onmouseup=Drag;

应该是:

copy.onmousedown=copy.onmousemove=copy.onmouseup=Drag;

drag = t 应该是drag = copy (?)

当我认为您打算将它们附加到“画布”部分时,您还将克隆附加到库存部分。

但也有一些不太明显的错误导致了不可靠性。例如,如果您将 mousemove 和 mouseup 事件附加到库存和克隆形状,那么如果拖得太快,您将不会收到事件。鼠标将移到形状之外,并且事件不会传递给形状。解决方法是将这些事件处理程序移动到根 SVG。

我所做的另一项更改是将克隆的 DOM 中的 xy 位置存储为 _x_y。这比尝试将它们保存在单独的数组中更容易。

无论如何,这是我对你的示例的修改版本,它的工作更加可靠。

// define meta objects
var drag = null;

var canvas = ;
var inventory = ;
	
window.onload = function() 
		
    canvas = document.getElementById("canvas");
	inventory = document.getElementById("inventory");
		
	// attach events listeners
	AttachListeners();


function AttachListeners() 
	var ttt = document.getElementsByClassName('inventory'), i;
	for (i = 0; i < ttt.length; i++) 
        document.getElementsByClassName("inventory")[i].onmousedown=Drag;
	
    document.getElementById("svg").onmousemove=Drag;
	document.getElementById("svg").onmouseup=Drag;


// Drag function that needs to be modified;//
function Drag(e) 
    var t = e.target, id = t.id, et = e.type;  m = MousePos(e);
  
	if (!drag && (et == "mousedown")) 
				
		if (t.className.baseVal=="inventory")  //if its inventory class item, this should get cloned into draggable?
	    	copy = t.cloneNode(true);
			copy.onmousedown = Drag;
            copy.removeAttribute("id");
            copy._x = 0;
            copy._y = 0;
			canvas.appendChild(copy);
			drag = copy;
			dPoint = m;
		 
		else if (t.className.baseVal=="draggable")	 //if its just draggable class - it can be dragged around
			drag = t;
			dPoint = m;
		
	

    // drag the spawned/copied draggable element now
	if (drag && (et == "mousemove")) 
		drag._x += m.x - dPoint.x;
		drag._y += m.y - dPoint.y;
		dPoint = m;
		drag.setAttribute("transform", "translate(" +drag._x+","+drag._y+")");	
	
		
    // stop drag
	if (drag && (et == "mouseup")) 
		drag.className.baseVal="draggable";
		drag = null;
	

         
		

// adjust mouse position to the matrix of SVG & screen size
function MousePos(event) 
		var p = svg.createSVGPoint();
		p.x = event.clientX;
		p.y = event.clientY;
		var matrix = svg.getScreenCTM();
		p = p.matrixTransform(matrix.inverse());
		return 
			x: p.x,
			y: p.y
		
/* SVG styles */
path

	stroke-width: 4;
	stroke: #000;
	stroke-linecap: round;


path.fill

	fill: #3ff;


html, body 
	margin: 0;
	padding: 0;
	border: 0;
	overflow:hidden;
	background-color: #fff;	

body 
	-ms-touch-action: none;

#canvasBackground 
	fill: lightgrey;

#inventoryBackground 
	fill: grey;

.inventory 
  fill: red;

.draggable 
  fill: green;

svg 
    position: fixed; 
	  top:0%; 
	  left:0%; 
	  width:100%; 
	  height:100%;  
<svg id="svg"
  
  
	viewbox="0 0 480 800"
	preserveAspectRatio="xMinYMin meet"
	xmlns="http://www.w3.org/2000/svg"
	xmlns:xlink="http://www.w3.org/1999/xlink"
>
	<rect id="canvasBackground"   x="0" y="0"/>
	<rect id="inventoryBackground"   x="0" y="480"/>
  

<g id="inventory">
<path id="curve4" class="inventory" d="M60,530 A35,35 0 1,1 60,531" />
<path id="curve3" class="inventory" d="M150,530 A35,35 0 1,1 150,531" />
<path id="curve2" class="inventory" d="M240,530 A35,35 0 1,1 240,531" />
<path id="curve1" class="inventory" d="M330,530 A35,35 0 1,1 330,531" />
</g>
  
<g id="canvas">
</g>

</svg>

【讨论】:

嘿,保罗,非常感谢;)我一步一步地经历了它,现在我对如何做这些事情有了更好的理解。

html鼠标拖动生成矩形svg(代码片段)

查看详情

简单实现svg的拖拽和缩放

...d3绘制svg放在页面,其中有一个功能就是对绘制的svg进行拖动和缩放,有点像地图。这里我已经写好了一个方法来绘制svg其中svg是要绘制的元素,data是要绘制的数据,x,y是svg的中心坐标,svgA是父元素的边长,来控制svg(正方形... 查看详情

如何将子元素以外的元素用作拖动手柄?

】如何将子元素以外的元素用作拖动手柄?【英文标题】:Howtouseotherthanachildelementasadraghandle?【发布时间】:2012-10-0314:13:28【问题描述】:我有以下代码(jsfiddled)。我想使用红色SVG矩形作为可拖动div元素的句柄,但是因为SVG元素... 查看详情

html5中哪个元素可以点击

...形,也是使用JS事件处理器,它的绘画能够按照像素重新生成。除此之外,在SVG中,每个图形都会被标记,只要SVG对象属性发生改变,浏览器就会自动重新生成相对应的新图像了,而在Canvas中,一旦图形完成,就会被遗忘,不会... 查看详情

如何通过在 svg 的选择框中拖动控件来使用鼠标指针调整旋转元素的大小?

】如何通过在svg的选择框中拖动控件来使用鼠标指针调整旋转元素的大小?【英文标题】:Howtoresizearotatedelementusingmousepointerbydraggingcontrolsintheselectboxforsvg?【发布时间】:2022-01-1006:21:04【问题描述】:我一直在尝试制作svg编辑器... 查看详情

SVG:拖动矩形仅在缓慢拖动时有效

】SVG:拖动矩形仅在缓慢拖动时有效【英文标题】:SVG:Draggingarectworksonlyifdraggingslowly【发布时间】:2014-06-2505:27:59【问题描述】:我有一个SVG矩形元素,需要在屏幕上拖动。问题是快速拖动时它不起作用。我把代码贴在jsFiddle。t... 查看详情

SVG 元素的 jQuery .hasClass() 方法失败

】SVG元素的jQuery.hasClass()方法失败【英文标题】:jQuery.hasClass()methodfailsforSVGelements【发布时间】:2013-07-2408:11:22【问题描述】:我有一组带有node和link类的SVG元素。我的程序应该在悬停在任何SVG元素上时检测元素是否具有node类或l... 查看详情

如何根据 CSS 确定 SVG 元素的实际属性

】如何根据CSS确定SVG元素的实际属性【英文标题】:HowtotodeterminetheactualattributeofanSVGElementbasedonCSS【发布时间】:2021-03-1222:29:57【问题描述】:我正在寻找一种方法来确定属性的实际值,例如SVG中包含的元素的填充或描边(路径... 查看详情

计算 SVG 文本高度和宽度的正确方法

...时间】:2014-06-0206:26:33【问题描述】:我需要计算svg文本元素的高度和宽度。有没有办法在不实际将其添加到我页面的DOM的情况下这样做?我只需要度量而不是实际元素。我既没有使用d3也没有使用Raphael,而只使用了纯JavaScript... 查看详情

如何自动缩放 <svg> 元素和内容? (d3.js)[重复]

...放到100%的宽度和高度,但是内容被剪裁了。svg是通过d3.js生成的HTML<s 查看详情

h5中元素的拖放

...在另一个位置属性和方法设置元素为可拖放(让元素可以拖动)<imgdraggable="true"> 拖动什么 事件:ondragstart—-规定当元素被拖动的时候会发生什么方法:dataTransfer.setData(数据类型,可拖动元素的id)—-设置被拖数据的数据... 查看详情

如何使用jquerydraggable和droppable实现拖拽功能

...求说明左侧的元素结构最后会通过Ajaxcall服务器的数据来生成能支持多级元素父节点可以折叠起来  用户可以通过拖放的操作将元素从左侧拖放到右侧如果是拖的父节点元素那么需要把它子节点的元素一并拖到右边  元素放... 查看详情

jQuery UI 重新生成(僵尸)可拖动元素

】jQueryUI重新生成(僵尸)可拖动元素【英文标题】:jQueryUIregenerate(zombie)draggableelements【发布时间】:2010-11-0918:15:30【问题描述】:我想知道如何使用jQueryUI创建可拖动元素,一旦将它们拖放到另一个容器中,就可以重新生成相... 查看详情

如何访问与 D3 SVG 对象相关的 DOM 元素?

...的basicbubblecharts之一来学习D3。第一个任务:弄清楚如何拖动一个气泡并让它在被拖动时成为最上面的对象。(问题是让D3的对象模型映射到DOM,但我会到达那里......)要拖 查看详情

如何使用jquerydraggable和droppable实现拖拽功能

...点是通过Ajax访问后台返回json数据,然后通过Javascript动态生成这种结构,而已不能为动态生成的元素绑定drag事件,也就不能调用draggable方法,所以我使用了一个称之“中间拖拽容易元素”,这div一直在页面上。只是默认不显示... 查看详情

如何获取 svg 元素的坐标?

】如何获取svg元素的坐标?【英文标题】:Howtogetcoordinatesofansvgelement?【发布时间】:2013-10-0921:10:26【问题描述】:我正在使用d3从相对svg位置绘制一条线,因此想要访问元素本身的坐标。我尝试过这样的事情(其中“this”指的... 查看详情

根据 SVG 元素顶部位置定位工具提示

...这个困住了:我得到了这个由300多个多边形组成的Raphael生成的SVG图形。我想在悬停多边形时显示工具提示。我希望工具提示位于悬停路径旁边。到目前为止,一切都很好...我可以使用.pageX和.pageY属性。现在,这 查看详情

将背景图像附加到嵌套的 SVG 元素

】将背景图像附加到嵌套的SVG元素【英文标题】:AttachbackgroundimagetonestedSVGelement【发布时间】:2015-07-0600:00:42【问题描述】:我正在尝试将PNG或JPG背景图像附加到SVG。目前,在尝试了多种不同的附加方法后,背景图像没有显示出... 查看详情