如何使用jQuery或JavaScript在基于SVG的对象上创建拖放?

时间:2016-01-21 15:54:47

标签: javascript jquery svg

我有一个SVG对象。我希望将它拖放到一个可以使用的区域。我通过我的document.body交换了"#name of svg object",但这不起作用。我听说SVG的问题是拖动偏移?由于top: e.pageYleft: 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;
    });
})

2 个答案:

答案 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;
&#13;
&#13;

这是纯粹的Javascript,而不是jQuery,但它阅读起来非常简单,并没有做任何复杂的事情。我认为你的系统无法工作的另一个原因是e.target还包括svg的孩子,这些孩子并没有真正受到CSS的影响(我试图实现类似的东西,但它一直在选择rect代替svg)。

我决定建议稍微不同的方法,请在下面查看:

&#13;
&#13;
// 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;
&#13;
&#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);