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

标签 javascript jquery svg

我有一个 SVG 对象。我希望将其拖放到将要参与的区域。我通过我的 "#name of svg object" 交换了 document.body,但这不起作用。我听说 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;
    });
})

最佳答案

这是一种思考拖动绝对定位对象的简单方法,也是检查它是否位于某个放置区域的方法。阅读我的小评论以获得更多解释。希望对您有帮助!

// 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' : '';
});
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;
}
<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>

这是纯 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;
});
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;
}
<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>

关于javascript - 如何使用 jQuery 或 JavaScript 在基于 SVG 的对象上创建拖放操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34928318/

相关文章:

javascript - javascript 引擎如何理解缩小的 JS 脚本?

javascript - 为什么 'keyup' 事件的 Bacon.combineAsArray 流会立即结束?

css - 动画 SVG 组

javascript - d3 : multiple tasks responding to one event

javascript - 使用模块模式的变体发出附加 javascript 事件的问题

JavaScript - 向变量声明函数是一个聪明的主意吗?

javascript - 将中国 MS Azure 认知服务与全局 WEB 认知服务整合

javascript - 单击浏览器后退按钮时调用 JavaScript 函数

javascript - jquery:如何等到ajax调用完成

asp.net-mvc - 除了 UI "flair"之外,你还用 jQuery 做什么?