【问题标题】:How to get target element in drag n drop d3 v4?如何在拖放 d3 v4 中获取目标元素?
【发布时间】:2018-07-12 11:17:36
【问题描述】:

我正在尝试 d3 v4 中的拖放功能。我正在努力获取目标元素。考虑一下在 droppped 时拖动小圆圈的示例,我想确定圆圈被丢弃在哪个路径上。

提前感谢您的帮助

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's 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>

【问题讨论】:

    标签: javascript d3.js drag-and-drop


    【解决方案1】:

    最直接最直接的解决方案可能是使用elementFromPoint

    例如,获取idid

    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's 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

    【讨论】:

    • 很好的解决方案!
    猜你喜欢
    • 2021-03-25
    • 2019-05-05
    • 2017-10-15
    • 2010-09-16
    • 2016-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多