我有一个SVG对象。我希望将它拖放到一个可以使用的区域。我通过我的document.body
交换了"#name of svg object"
,但这不起作用。我听说SVG的问题是拖动偏移?由于top: e.pageY
和left: e.pageX
,但我不知道为什么。我尝试使用翻译和鼠标,但它不起作用。
$(document).ready(function() {
var $dragging = null;
$(document.body).on("mousemove", function(e) {
if ($dragging) {
$dragging.offset({
top: e.pageY,
left: e.pageX
});
}
});
$(document.body).on("mousedown", function (e) {
$dragging = $(e.target);
console.log($dragging);
});
$(document.body).on("mouseup", function (e) {
console.log($dragging);
$dragging = null;
});
})
答案 0 :(得分:1)
这是一种考虑拖动绝对定位对象的简单方法,也是一种检查它是否在某个dropzone中的方法。阅读我的小评论以获得更多解释。希望它有所帮助!
// Lets get the SVG element and the dropZone
var SVG = document.getElementById('mySVG');
var Zone = document.getElementById('dropZone')
// We will store some global mouse info here, to calculate differences
var mouse = {x:0, y:0, down: false}
// This function will return true or false depending on whether the 'zone' and 'what' overlap
// http://stackoverflow.com/questions/12066870/how-to-check-if-an-element-is-overlapping-other-elements
function inDropZone(what, zone){
zone = zone.getBoundingClientRect();
what = what.getBoundingClientRect();
return !(
zone.right < what.left ||
zone.left > what.right ||
zone.bottom < what.top ||
zone.top > what.bottom
);
}
// This will set the drag to true so the mousemove can do its thing.
SVG.addEventListener('mousedown', function(e){
mouse.down = true;
});
// This will only move the svg if mouse.down is true
document.addEventListener('mousemove', function(e){
if(mouse.down){
// Because the current position is stored as a String, we will use parseInt.
// But since the SVG can also have an empty position value, we need to make sure
// we output a number, so if parseInt fails, we use the value `0`
SVG.style.left = (parseInt(SVG.style.left, 10) || 0) + e.pageX - mouse.x + 'px';
SVG.style.top = (parseInt(SVG.style.top, 10) || 0) + e.pageY - mouse.y + 'px';
}
// This will continually reset the mouse position so we can drop and restart dragging at any time
mouse.x = e.pageX;
mouse.y = e.pageY;
});
// This will deactivate the mousedown and mark the drozone when the element is released.
document.addEventListener('mouseup', function(e){
mouse.down = false;
Zone.className = inDropZone(SVG, Zone) ? 'dropped' : '';
});
&#13;
svg {
position: absolute;
left: 0;
top: 0;
z-index: 1;
}
#dropZone {
position: absolute;
right: 20px;
bottom: 20px;
width: 100px;
height: 100px;
border: 1px solid black;
}
#dropZone.dropped {
background: red;
}
&#13;
<svg viewBox="0 0 10 10" width="100" height="100" id="mySVG">
<rect x="1" y="1" width="8" height="8" fill="green" />
</svg>
<div id="dropZone"></div>
&#13;
这是纯粹的Javascript,而不是jQuery,但它阅读起来非常简单,并没有做任何复杂的事情。我认为你的系统无法工作的另一个原因是e.target
还包括svg
的孩子,这些孩子并没有真正受到CSS的影响(我试图实现类似的东西,但它一直在选择rect
代替svg
)。
我决定建议稍微不同的方法,请在下面查看:
// Lets get the dropZone
var Zone = document.getElementById('dropZone')
// Let's also get all the elements with a class of 'draggable'.
var Draggables = document.querySelectorAll('.draggable');
// We use the Array.prototype.slice.call to turn the above into a simple Array for eadsier use later
Draggables = Array.prototype.slice.call(Draggables);
// We will store some global mouse info here, to calculate differences
var mouse = {x:0, y:0, down: false}
// This function will return true or false depending on whether the 'zone' and 'what' overlap
// http://stackoverflow.com/questions/12066870/how-to-check-if-an-element-is-overlapping-other-elements
function inDropZone(what, zone){
zone = zone.getBoundingClientRect();
what = what.getBoundingClientRect();
return !(
zone.right < what.left ||
zone.left > what.right ||
zone.bottom < what.top ||
zone.top > what.bottom
);
}
Draggables.forEach(function(element){
// This will set the drag to true so the mousemove can do its thing.
element.addEventListener('mousedown', function(e){
mouse.down = element;
});
});
// This will only move the svg if mouse.down is true
document.addEventListener('mousemove', function(e){
if(mouse.down){
mouse.down.style.left = (parseInt(mouse.down.style.left, 10) || 0) + e.pageX - mouse.x + 'px';
mouse.down.style.top = (parseInt(mouse.down.style.top, 10) || 0) + e.pageY - mouse.y + 'px';
}
// This will continually reset the mouse position so we can driop and restart dragging
mouse.x = e.pageX;
mouse.y = e.pageY;
});
// This will deactivate the mousedown and mark the drozone when the element is released.
document.addEventListener('mouseup', function(e){
if(mouse.down) Zone.className = inDropZone(mouse.down, Zone) ? 'dropped' : '';
mouse.down = false;
});
&#13;
svg {
position: absolute;
left: 0;
top: 0;
z-index: 1;
}
#dropZone {
position: absolute;
right: 20px;
bottom: 20px;
width: 100px;
height: 100px;
border: 1px solid black;
}
#dropZone.dropped {
background: red;
}
&#13;
<svg viewBox="0 0 10 10" width="100" height="100" class="draggable">
<rect x="1" y="1" width="8" height="8" fill="green" />
</svg>
<svg viewBox="0 0 10 10" width="100" height="100" class="draggable">
<rect x="1" y="1" width="8" height="8" fill="yellow" />
</svg>
<div id="dropZone"></div>
&#13;
答案 1 :(得分:0)
你需要一个事件处理程序来对svg元素上的mousedown事件进行处理
在事件处理程序内部,将两个事件处理程序设置为mousemove和mouseup事件
mousemove事件处理程序必须处理svg视口coords计算
mouseup只是清理你设置为mousemove和mouse事件的处理程序。
简而言之,这就是如何处理拖动鼠标事件。
关于计算,这是一个尝试和错误的过程。我刚刚完成了,您可以在this fiddle中看到它。
var viewBox = svg.getAttribute('viewBox');
viewBox = viewBox.split(' ');
var vwx = parseFloat(viewBox[0]);
var vwy = parseFloat(viewBox[1]);
var xy = getSvgCordinates(event);
var x = xy.x;
var y = xy.y;
var x0 = xy0.x;
var y0 = xy0.y;
var dx = (x - x0);
var dy = (y - y0);
var xnew, ynew;
var xnew = vwx - dx;
var ynew = vwy - dy;
var s = 'XY0 (coord.click): ' + x0 + ',' + y0 + '\n' +
'XY (coord.drag): ' + x + ',' + y + '\n' +
'VW (coord.viewport): ' + vwx + ',' + vwy + '\n' +
'XY-XY0: ' + dx + ',' + dy + '\n' +
'VMNEW: ' + xnew + ',' + ynew;
texto.innerText = s;
viewBox = xnew + ' ' + ynew + ' ' + viewBox[2] + ' ' + viewBox[3];
svg.setAttribute('viewBox', viewBox);