SVG 可拖动使用 JQuery 和 Jquery-svg
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1108480/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SVG draggable using JQuery and Jquery-svg
提问by skyfoot
I have an HTML 5 page where I load an svg circle. When I click on the circle I create another small circle where I click. I want to be able to drag the second circle but cant seem to do it with jquery-ui .draggable();
我有一个 HTML 5 页面,我在其中加载了一个 svg 圆圈。当我点击圆圈时,我会在点击的地方创建另一个小圆圈。我希望能够拖动第二个圆圈,但似乎无法使用 jquery-ui .draggable();
I am able to move the circle by accessing its cx and cy attributes so there must be a way to drag it.
我可以通过访问其 cx 和 cy 属性来移动圆圈,因此必须有一种方法可以拖动它。
<!DOCTYPE HTML>
<html >
<head>
<title></title>
<link href="css/reset.css" rel="stylesheet" type="text/css">
<link href="css/layout.css" rel="stylesheet" type="text/css">
<link href="css/style.css" rel="stylesheet" type="text/css">
<script src="js/jquery.js" type="text/javascript" ></script>
<script src="js/jquerysvg/jquery.svg.js" type="text/javascript" ></script>
<script src="js/jquery-ui.js" type="text/javascript" ></script>
<script type="text/javascript" >
jQuery(document).ready(function(){
$('#target').svg({onLoad: drawInitial});
$('circle').click(function(e){
drawShape(e);
var shape = this.id;
});
$('.drag').mousedown(function(e){
var shape = this.id;
this.setAttribute("cx", e.pageX);
this.setAttribute("cy", e.pageY);
});
})
function drawInitial(svg) {
svg.add($('#svginline'));
}
function drawShape(e) {
var svg = $("#target").svg('get');
$('#result').text(e.clientX + ": " + e.pageX);
var dragme = svg.circle(e.clientX, e.clientY, 5, {fill: 'green', stroke: 'red', 'stroke-width': 3, class_: 'drag'});
//$(dragme).draggable();
}
</script>
</head>
<body>
<div id="target" ></div>
<svg:svg id="svginline">
<svg:circle id="circ11" class="area" cx="75" cy="75" r="50" stroke="black" stroke-width="2" fill="red"/>
</svg:svg>
<div id="result" >ffff</div>
</body>
</html>
回答by tkdave
jQuery UI draggable behavior does work, but you need to update the position manually in the drag handler, as relative CSS positioning doesn't work inside SVG.
jQuery UI 可拖动行为确实有效,但您需要在拖动处理程序中手动更新位置,因为相对 CSS 定位在 SVG 中不起作用。
svg.rect(20,10,100,50, 10, 10, {fill:'#666'});
svg.rect(40,20,100,50, 10, 10, {fill:'#999'});
svg.rect(60,30,100,50, 10, 10, {fill:'#ccc'});
$('rect')
.draggable()
.bind('mousedown', function(event, ui){
// bring target to front
$(event.target.parentElement).append( event.target );
})
.bind('drag', function(event, ui){
// update coordinates manually, since top/left style props don't work on SVG
event.target.setAttribute('x', ui.position.left);
event.target.setAttribute('y', ui.position.top);
});
回答by galdre
This linkhas an excellent description of how to solve the problem in general (i.e., without requiring JQuery), and that is definitely the best solution I've seen. However, I wanted to keep using JQuery's excellent Draggable API.
这个链接很好地描述了如何解决一般问题(即,不需要 JQuery),这绝对是我见过的最好的解决方案。但是,我想继续使用 JQuery 出色的 Draggable API。
I recently spent a couple days hammering at this problem. The accepted answer above is what I tried first, but I couldn't get it to work right in Firefox. There's something about how browsers handleSVG coordinates differently.
我最近花了几天时间来解决这个问题。上面接受的答案是我首先尝试的,但我无法在 Firefox 中正常工作。浏览器处理SVG 坐标的方式有些不同。
I came up with a solution that worked fairly well for me, in both Chrome and Firefox, and lets me keep using JQuery UI. I haven't tested it everywhere. It's definitely a hack.
我想出了一个对我来说效果很好的解决方案,在 Chrome 和 Firefox 中都运行良好,并让我继续使用 JQuery UI。我没有到处测试。这绝对是一个黑客。
You can see a quick mock-up of what I did in a fiddle here. The key idea is to use a proxy div which you keep hovering exactly over the svg element you want to drag. Then you change the svg element's x and y coordinates as you drag the proxy div. Something like this:
你可以在这里看到我在小提琴中所做的快速模型。关键思想是使用代理 div,您可以将其准确悬停在要拖动的 svg 元素上。然后在拖动代理 div 时更改 svg 元素的 x 和 y 坐标。像这样的东西:
$('#proxy').on('drag', function(e)
{
t = $('#background');
prox = $('#proxy');
t.attr('x', t.attr('x')*1
+ prox.css('left').slice(0,-2)*1
- prox.data('position').left)
.attr('y', t.attr('y')*1
+ prox.css('top').slice(0,-2)*1
- prox.data('position').top);
prox.data('position',{top : prox.css('top').slice(0,-2)*1,
left: prox.css('left').slice(0,-2)*1}
);
});
In my case the SVG element I wanted to drag would always fill a certain square on the screen, so it was very easy to position the proxy div over the target. In other situations it could be much more difficult. It's also not too hard to use the 'containment' option to make sure you don't drag the background outside the frame...it just takes some careful math and you have to reset the containment in between each drag.
在我的例子中,我想要拖动的 SVG 元素总是会填充屏幕上的某个方块,因此很容易将代理 div 定位在目标上方。在其他情况下,这可能要困难得多。使用“包含”选项来确保您不会将背景拖到框架之外也不太难……它只需要一些仔细的数学计算,并且您必须在每次拖动之间重置包含。
To make this applicable to more SVG elements, you could use transforms rather than x and y coordinates.
为了使其适用于更多 SVG 元素,您可以使用变换而不是 x 和 y 坐标。
回答by Mike
The solution I'm tinkering with involves (to tie it to your case) creating a new div and svg, positioned over the original shape, to act as the handle for the targeted svg object. Make the handle div draggable and store the starting top/left offset externally (think hidden div). Once the "stop" event for the draggable div is fired, figure out the degree of change for the top and left (stopX-startX=changeX) and apply that to the original shapes coordinates. Then .remove() your temporary shape.
我正在修补的解决方案涉及(将其与您的情况联系起来)创建一个新的 div 和 svg,位于原始形状上,作为目标 svg 对象的句柄。使手柄 div 可拖动并在外部存储起始上/左偏移量(想想隐藏的 div)。一旦可拖动 div 的“停止”事件被触发,计算顶部和左侧的变化程度 (stopX-startX=changeX) 并将其应用于原始形状坐标。然后 .remove() 你的临时形状。
回答by Philippe Perret
Just put the svg in a draggable div.
只需将 svg 放在可拖动的 div 中。
//*
$(document).ready(function(){
$('#mydiv').draggable();
});
//*/
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="mydiv">
<svg xml:lang="en"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<text class="main" x="10" transform="rotate(-28 0 0)" y="90">Sol min</text>
<text class="sous" x="4" y="110" transform="rotate(-28 0 20)">(SOUS DOM.)</text>
<line stroke="black" stroke-width="2" x1="10" y1="100" x2="110" y2="46" />
<line stroke="red" stroke-width=2 x1=10 y1=99 x2=10 y2=140 />
</svg>
</div>
回答by skyfoot
I have created a basic drag drop function to target my svg objects. I dont have any containment or collistion detection. There is an issue if I move the mouse too quicly I will leave the draggable object behind.
我创建了一个基本的拖放功能来定位我的 svg 对象。我没有任何遏制或碰撞检测。如果我将鼠标移动得太快,则会出现问题,我会将可拖动对象留在后面。
<!DOCTYPE HTML>
<html >
<head>
<title></title>
<link href="css/reset.css" rel="stylesheet" type="text/css">
<link href="css/layout.css" rel="stylesheet" type="text/css">
<link href="css/style.css" rel="stylesheet" type="text/css">
<script src="js/jquery.js" type="text/javascript" ></script>
<script src="js/jquery-ui.js" type="text/javascript" ></script>
<script src="js/jquerysvg/jquery.svg.js" type="text/javascript" ></script>
<script src="js/jquerysvg/jquery.svgdom.js" type="text/javascript" ></script>
<script type="text/javascript" >
jQuery(document).ready(function(){
$('#target').svg({onLoad: drawInitial});
$('circle').click(function(e){
drawShape(e);
var shape = this.id;
});
})
function drawInitial(svg) {
svg.add($('#svginline'));
}
function onMouseDown(evt){
//var shape = this.id;
var target = evt.target;
target.onmousemove = onMouseMove;
return false;
}
function onMouseMove(evt){
circle = evt.target
var cx = circle.getAttribute("cx");
offsetX = $('#target').offset().left;
offsetY = $('#target').offset().top
circle.setAttribute("cx", evt.clientX -offsetX);
circle.setAttribute("cy", evt.clientY - offsetY);
circle.onmouseup = OnMouseUp;
}
function OnMouseUp(evt) {
var target = evt.target;
target.onmousemove = null;
}
function drawShape(e) {
var svg = $("#target").svg('get');
offsetX = $('#target').offset().left;
offsetY = $('#target').offset().top;
$('#result').text(e.clientX + ": " + e.pageX);
var dragme = svg.circle(e.clientX - offsetX, e.clientY - offsetY, 5, {onmousedown: "onMouseDown(evt)",fill: 'green', stroke: 'red', 'stroke-width': 3});
$(dragme).addClass('drag');
}
</script>
</head>
<body>
<div id="target" ></div>
<svg:svg id="svginline">
<svg:circle id="circ11" class="area" cx="75" cy="75" r="50" stroke="black" stroke-width="2" fill="red"/>
</svg:svg>
<div id="result" >ffff</div>
</body>
</html>