Как получить целевой элемент в drag n drop d3 v4?

1

Я пытаюсь использовать функцию перетаскивания n в d3 v4. Я пытаюсь получить элемент цели. рассмотрим пример перетаскивания малого круга во время падения. Я хочу определить, на каком пути был отброшен круг.

заранее спасибо за помощь

d3.selection.prototype.moveToFront = function() {  
      return this.each(function(){
        this.parentNode.appendChild(this);
      });
    };
    
    // Feel free to change or delete any of the code you see in this editor!
    const svg = d3.select("body").append("svg")
      .attr("width", 960)
      .attr("height", 960)
      
    
    const svgp = svg.append("g")
			.attr("transform", "translate(400,300)")
      // set constants
      var PI = Math.PI;
      var arcMin = 0;        // inner radius of the first arc
      var arcWidth = 25;      // width
      var arcPad = 0;         // padding between arcs
      var pieces = 4;

      var arcPieces = [{start:0,end:90},{start:90,end:180},{start:180,end:270},{start:270,end:360}];
    
      var drawArc = d3.arc()
      .innerRadius(function(d, i) {
        return  d.ir;
      })
      .outerRadius(function(d, i) {
        return d.or;
      })
      .startAngle(function(d, i) {
        //console.log(d);
        return d.start * Math.PI/180;
      })
      .endAngle(function(d, i) {
        return (d.end * Math.PI/180);
      });
      
    var q = ["q1","q2","q3","q4"];
    var p = [1,2,3,4,5,6,7,8,9,10];
    var step = 360/q.length;
    var objData = []
    var drawData = q.forEach((q,i)=>{
      p.forEach((p,j)=>{
        objData.push({
          q:q,
          p:p,
          start:(i*step),
          end:((i+1)*step),
          ir : j*25,
          or : (j+1) *25
        })
      })
    });
    
  
   
  //console.log(objData);
    
    
        // bind the data
      var arcs = svgp.selectAll("path.arc-path").data(objData);

      arcs.enter().append("svg:path")
          .attr("class", "arc-path")                  // assigns a class for easier selecting
          .attr("id",(d)=>d.q+"-"+d.p)
              // sets position--easier than setting x and y's
          .attr("fill", function(d,i){
              // fill is an rgb value with the green value determined by the data
              // smaller numbers result in a higher green value (1 - d/60)
              // you should also look into using d3 scales to create gradients
            //var grn = Math.floor((1 - d/60)*255);
            //console.log((d.q.replace("q",'')*10));
            return "rgb(0, 0,"+ (d.q.replace("q",'')*20) +")";
          })
          .attr("d", drawArc)     // draw the arc
          .on('click',function(d){
        		//console.log(d);
      		})
          .on('mouseover',function(){
        //d3.select(this).attr("fill","#ffffff");
      })
      .on('dragover',function(){
        alert("on arc")
      })
      
      
      var circleC = svg.append("circle").attr("cx",25).attr("cy",25).attr("r",10)
      .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended));
    
    function dragstarted(d,e){
      //console.log("s",d,e);
      d3.select(this).raise().classed("active", true);
    }
    
    function dragged(d,e){
      //console.log(d3.event,event,this);
      circleC.attr("cx",d3.event.x)
      circleC.attr("cy",d3.event.y)
    }
    
    function dragended(d,e){
      //I want to get on which path is is dropped
      //console.log("e",d,e)
    }
<script src="https://d3js.org/d3.v4.min.js"></script>
Теги:
d3.js
drag-and-drop

1 ответ

2
Лучший ответ

Самое прямое и простое решение, вероятно, использует elementFromPoint.

Например, получение id <path>:

d3.select(document.elementFromPoint(d3.event.sourceEvent.clientX, d3.event.sourceEvent.clientY))
    .attr("id");

Чтобы это сработало, мы должны сначала lower круг, чтобы он не был на вершине путей.

Вот ваш обновленный код:

d3.selection.prototype.moveToFront = function() {
  return this.each(function() {
    this.parentNode.appendChild(this);
  });
};

// Feel free to change or delete any of the code you see in this editor!
const svg = d3.select("body").append("svg")
  .attr("width", 960)
  .attr("height", 960)


const svgp = svg.append("g")
  .attr("transform", "translate(400,300)")
// set constants
var PI = Math.PI;
var arcMin = 0; // inner radius of the first arc
var arcWidth = 25; // width
var arcPad = 0; // padding between arcs
var pieces = 4;

var arcPieces = [{
  start: 0,
  end: 90
}, {
  start: 90,
  end: 180
}, {
  start: 180,
  end: 270
}, {
  start: 270,
  end: 360
}];

var drawArc = d3.arc()
  .innerRadius(function(d, i) {
    return d.ir;
  })
  .outerRadius(function(d, i) {
    return d.or;
  })
  .startAngle(function(d, i) {
    //console.log(d);
    return d.start * Math.PI / 180;
  })
  .endAngle(function(d, i) {
    return (d.end * Math.PI / 180);
  });

var q = ["q1", "q2", "q3", "q4"];
var p = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var step = 360 / q.length;
var objData = []
var drawData = q.forEach((q, i) => {
  p.forEach((p, j) => {
    objData.push({
      q: q,
      p: p,
      start: (i * step),
      end: ((i + 1) * step),
      ir: j * 25,
      or: (j + 1) * 25
    })
  })
});



//console.log(objData);


// bind the data
var arcs = svgp.selectAll("path.arc-path").data(objData);

arcs.enter().append("svg:path")
  .attr("class", "arc-path") // assigns a class for easier selecting
  .attr("id", (d) => d.q + "-" + d.p)
  // sets position--easier than setting x and y's
  .attr("fill", function(d, i) {
    // fill is an rgb value with the green value determined by the data
    // smaller numbers result in a higher green value (1 - d/60)
    // you should also look into using d3 scales to create gradients
    //var grn = Math.floor((1 - d/60)*255);
    //console.log((d.q.replace("q",'')*10));
    return "rgb(0, 0," + (d.q.replace("q", '') * 20) + ")";
  })
  .attr("d", drawArc) // draw the arc
  .on('click', function(d) {
    //console.log(d);
  })
  .on('mouseover', function() {
    //d3.select(this).attr("fill","#ffffff");
  })
  .on('dragover', function() {
    alert("on arc")
  })


var circleC = svg.append("circle").attr("cx", 25).attr("cy", 25).attr("r", 10)
  .call(d3.drag()
    .on("start", dragstarted)
    .on("drag", dragged)
    .on("end", dragended));

function dragstarted(d, e) {
  //console.log("s",d,e);
  d3.select(this).raise().classed("active", true);
}

function dragged(d, e) {
  //console.log(d3.event,event,this);
  circleC.attr("cx", d3.event.x)
  circleC.attr("cy", d3.event.y)
}

function dragended(d, e) {
  //I want to get on which path is is dropped
  d3.select(this).lower();
  console.log(d3.select(document.elementFromPoint(d3.event.sourceEvent.clientX, d3.event.sourceEvent.clientY)).attr("id"));
  d3.select(this).raise();
}
<script src="https://d3js.org/d3.v4.min.js"></script>

Поскольку для самого SVG нет id, если вы вычеркнете круг за пределами путей, вы получите null.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню