简体   繁体   English

D3js拖放对象并检测将其放置在何处。

[英]D3js drag&drop an object and detect where it is dropped.

I am working on dragging and dropping svg using d3js. 我正在使用d3js拖放svg。 There are two problems and I think they are related to each other. 有两个问题,我认为它们是相互关联的。

  1. When the circle is dropped it has to detect that it was dropped into the rectangle. 放下圆后,它必须检测到它已落入矩形中。 Some of the examples that I have looked at uses x and y coordinates of the mouse, but I don't fully understand it. 我看过的一些示例使用鼠标的x和y坐标,但我并不完全理解。

  2. Another problem is that the circle appears behind the rectangle. 另一个问题是圆形出现在矩形后面。 Is there a way to bring it to the front when the circle is moving around without changing the order of where the circle and rectangle are created ie(create circle first and then rectangle). 当圆移动时,有没有一种方法可以在不改变圆和矩形创建位置的顺序的情况下将其显示在前面(即先创建圆,然后创建矩形)。

 var width = window.innerWidth, height = window.innerHeight; var drag = d3.behavior.drag() .on("dragstart", dragstarted) .on("drag", dragged) .on("dragend", dragended); //create circle and space evenly var svg = d3.select("body") .append("svg") .attr("width", width) .attr("height", height); var circle = d3.select("svg") .append("circle") .attr("cx", 50) .attr("cy", 30) .attr("r", 15) .attr("transform", "translate(0,0)") .style("stroke", "black") .call(drag); function dragstarted(d) { d3.event.sourceEvent.stopPropagation(); } function dragged(d) { d3.select(this).attr("transform", "translate(" + [d3.event.x, d3.event.y] + ")"); } function dragended(d) { d3.event.sourceEvent.stopPropagation(); // here would be some way to detect if the circle is dropped inside the rect. } var ellipse = svg.append("rect") .attr("x", 150) .attr("y", 50) .attr("width", 50) .attr("height", 140) .attr("fill", "green"); 
 <script src="https://d3js.org/d3.v3.min.js"></script> 

Any help is appreciated. 任何帮助表示赞赏。

Updated to still include the bounding client rectangle, but iterate through any number of rectangles that exist. 已更新为仍包括边界客户端矩形,但迭代存在的任何数量的矩形。 New Fiddle here. 新小提琴在这里。

Here's my solution to the problem. 这是我解决问题的方法。 I used a great little "moveToBack" helper function seen here to move the rect to the back without changing the order in which it appears. 我用一个伟大的小“moveToBack”辅助函数在这里看到移动RECT到后面不改变它出现的顺序。

To get the positions of the circle and rectangle, I made heavy use of the vanilla js getBoundingClientRect() method. 为了获得圆形和矩形的位置,我大量使用了香草js的getBoundingClientRect()方法。 You can see all this together in this JS Fiddle . 您可以在JS Fiddle中一起看到所有这些内容。

var width = window.innerWidth,
  height = window.innerHeight;

var drag = d3.behavior.drag()
  .on("dragstart", dragstarted)
  .on("drag", dragged)
  .on("dragend", dragended);

//create circle and space evenly
var svg = d3.select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

var circle = d3.select("svg")
  .append("circle")
  .attr("r", 15)
  .attr("transform", "translate(50,30)")
  .style("stroke", "black")
  .attr("id", "circle")
  .call(drag);


d3.selection.prototype.moveToBack = function() {  
  return this.each(function() { 
    var firstChild = this.parentNode.firstChild; 
    if (firstChild) { 
      this.parentNode.insertBefore(this, firstChild); 
    } 
  });
};

var rect = svg.append("rect")
      .attr("x", 150)
      .attr("y", 50)
      .attr("width", 50)
      .attr("height", 140)
      .attr("fill", "green")
      .attr("id", "rect")
      .moveToBack();

var rect2 = svg.append("rect")
      .attr("x", 350)
      .attr("y", 50)
      .attr("width", 50)
      .attr("height", 140)
      .attr("fill", "green")
      .attr("id", "rect")
      .moveToBack();

function dragstarted(d) {
  d3.event.sourceEvent.stopPropagation();
}

function dragged(d) {
  d3.select(this).attr("transform", "translate(" + d3.event.x + "," + d3.event.y + ")");
}

function dragended(d) {
  // Define boundary
  var rects = document.querySelectorAll("rect");
  for (var i = 0; i < rects.length; i++) {
    var rectDimensions = rects[i].getBoundingClientRect();
    var xmin = rectDimensions.x;
    var ymin = rectDimensions.y;
    var xmax = rectDimensions.x + rectDimensions.width;
    var ymax = rectDimensions.y + rectDimensions.height;
    // Get circle position
    var circlePos = document.getElementById("circle").getBoundingClientRect();
    var x1 = circlePos.x;
    var y1 = circlePos.y;
    var x2 = circlePos.x + circlePos.width;
    var y2 = circlePos.y + circlePos.height;
    if(x2 >= xmin && x1 <= xmax && y2 >= ymin && y1 <= ymax) {
      rects[i].setAttribute("fill", "red");
    } else {
      rects[i].setAttribute("fill", "green");
    }  
  }
  d3.event.sourceEvent.stopPropagation();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM