【问题标题】:How to drag a path in d3.js如何在 d3.js 中拖动路径
【发布时间】:2018-10-16 15:11:36
【问题描述】:

我不知道如何使用 d3.js 围绕 svg 对象拖动路径

具体来说,我有一个呈现为 svg 路径的正态分布形状,我希望能够单击它并将其拖动到 svg 空间周围(但这个特定形状没有什么独特之处等)。

我见过点、直线和形状的例子,但不是路径。

我的简化代码如下。除非我偏离了标记,否则我怀疑错误出在底部的拖动功能上。

Javascript:

// width and height for svg object

var w = 500;
var h = 500;

/// setting up svg object 

var svg = d3.select("body")
            .append("svg")
            .attr("width", w)
            .attr("height", h)


// Values for calculating pdf of normal distribution 
var sigma = 4;
var mu = 0;
var N = 10;
var step = 0.1;
var dataset = [];
var x;

// creating the pdf of the normal distribution and plotting it for -N to N
var C = 1/(sigma*Math.sqrt(2*Math.PI));
for (x=-N; x < N; x += step) {
    var E = (x-mu)/sigma;
    E = -(E*E)/2;
    var d = C*Math.exp(E);
    dataset.push(d);
}


// Scales slightly over fancy, required for features stripped out
var overlap = w*0.1;
var xscale1 = d3.scale.linear().range([0, w/2+overlap]).domain([0, dataset.length-1]).clamp(true);
var xscale2 = d3.scale.linear().range([w/2-overlap, w]).domain([0, dataset.length-1]).clamp(true);



// So specifies the height as max in dataset and it takes up 1/2 the svg
var yscale = d3.scale.linear().domain([0, d3.max(dataset)]).range([h,h/2]);
var area1 = d3.svg.area()
    .x(function(d,i) { return xscale1(i); })
    .y0(h)
    .y1(function(d,i) { return yscale(d); });

 // plots filled normal distribution to svg  
g1 = svg.append("path")
      .datum(dataset)
      .attr("class", "area1")
      .attr("d", area1)
      .attr("opacity",0.75);

// Problem is probably with the below line and related function dragged
d3.select("path.area1").on("drag", dragged);


function dragged() {
        var dx = d3.event.dx,
           dy = d3.event.dy;
  d3.select(this)
     .attr("transform", path => "translate(" + dx + "," + dy + ")");
}

【问题讨论】:

    标签: d3.js svg path drag


    【解决方案1】:

    这是实现拖动的代码版本:

    var w = 500;
    var h = 250;
    
    var svg = d3.select("body")
                .append("svg")
                .attr("width", w)
                .attr("height", h);
    
    // Values for calculating pdf of normal distribution 
    var sigma = 4;
    var mu = 0;
    var N = 10;
    var step = 0.1;
    var dataset = [];
    var x;
    
    // creating the pdf of the normal distribution and plotting it for -N to N
    var C = 1/(sigma*Math.sqrt(2*Math.PI));
    for (x=-N; x < N; x += step) {
        var E = (x-mu)/sigma;
        E = -(E*E)/2;
        var d = C*Math.exp(E);
        dataset.push(d);
    }
    
    
    // Scales slightly over fancy, required for features stripped out
    var overlap = w*0.1;
    var xscale1 = d3.scale.linear().range([0, w/2+overlap]).domain([0, dataset.length-1]).clamp(true);
    var xscale2 = d3.scale.linear().range([w/2-overlap, w]).domain([0, dataset.length-1]).clamp(true);
    
    
    
    // So specifies the height as max in dataset and it takes up 1/2 the svg
    var yscale = d3.scale.linear().domain([0, d3.max(dataset)]).range([h,h/2]);
    var area1 = d3.svg.area()
        .x(function(d,i) { return xscale1(i); })
        .y0(h)
        .y1(function(d,i) { return yscale(d); });
    
    svg.append("path")
      .datum(dataset)
      .attr("class", "area1")
      .attr("d", area1)
      .attr("opacity",0.75)
      .call(d3.behavior.drag().on("drag", dragged));
    
    function dragged(d) {
    
      // Current position:
      this.x = this.x || 0;
      this.y = this.y || 0;
      // Update thee position with the delta x and y applied by the drag:
      this.x += d3.event.dx;
      this.y += d3.event.dy;
    
      // Apply the translation to the shape:
      d3.select(this)
        .attr("transform", "translate(" + this.x + "," + this.y + ")");
    }
    <body></body>
    <script src="https://d3js.org/d3.v3.min.js"></script>

    这实际上与其他类型的形状上的任何其他拖动完全相同。您只需在选定节点上应用拖动行为。

    这里是负责拖拽实现的部分:

    svg.append("path")
      .datum(dataset)
      .attr("d", area1)
      ...
      .call(d3.behavior.drag().on("drag", dragged));
    
    function dragged(d) {
    
      // Current position:
      this.x = this.x || 0;
      this.y = this.y || 0;
      // Update thee position with the delta x and y applied by the drag:
      this.x += d3.event.dx;
      this.y += d3.event.dy;
    
      // Apply the translation to the shape:
      d3.select(this)
        .attr("transform", "translate(" + this.x + "," + this.y + ")");
    }
    

    您错过的主要事情是您从事件中收到的dxdy 是鼠标的移动(移动的“增量”)。这些动作不能成为形状的新位置。它们必须添加到现有的xy 形状的当前位置。


    这里是相同的代码,但用于 d3 的第 4 版:

    var w = 500;
    var h = 250;
    
    var svg = d3.select("body").append("svg").attr("width", w).attr("height", h)
    
    // Values for calculating pdf of normal distribution 
    var sigma = 4;
    var mu = 0;
    var N = 10;
    var step = 0.1;
    var dataset = [];
    var x;
    
    // creating the pdf of the normal distribution and plotting it for -N to N
    var C = 1/(sigma*Math.sqrt(2*Math.PI));
    for (x=-N; x < N; x += step) {
        var E = (x-mu)/sigma;
        E = -(E*E)/2;
        var d = C*Math.exp(E);
        dataset.push(d);
    }
    
    // Scales slightly over fancy, required for features stripped out
    var overlap = w*0.1;
    var xscale1 = d3.scaleLinear().range([0, w/2+overlap]).domain([0, dataset.length-1]).clamp(true);
    var xscale2 = d3.scaleLinear().range([w/2-overlap, w]).domain([0, dataset.length-1]).clamp(true);
    
    // So specifies the height as max in dataset and it takes up 1/2 the svg
    var yscale = d3.scaleLinear().domain([0, d3.max(dataset)]).range([h,h/2]);
    var area1 = d3.area()
        .x(function(d,i) { return xscale1(i); })
        .y0(h)
        .y1(function(d,i) { return yscale(d); });
    
     // plots filled normal distribution to svg  
    g1 = svg.append("path")
          .datum(dataset)
          .attr("class", "area1")
          .attr("d", area1)
          .attr("opacity",0.75)
          .call(d3.drag().on("drag", dragged));
    
    function dragged(d) {
    
      // Current position:
      this.x = this.x || 0;
      this.y = this.y || 0;
      // Update thee position with the delta x and y applied by the drag:
      this.x += d3.event.dx;
      this.y += d3.event.dy;
    
      // Apply the translation to the shape:
      d3.select(this)
      	.attr("transform", "translate(" + this.x + "," + this.y + ")");
    }
    <body></body>
    <script src="https://d3js.org/d3.v4.min.js"></script>

    【讨论】:

      猜你喜欢
      • 2016-11-09
      • 2021-09-02
      • 1970-01-01
      • 1970-01-01
      • 2021-01-25
      • 2013-04-03
      • 1970-01-01
      • 1970-01-01
      • 2013-06-18
      相关资源
      最近更新 更多