如何在 d3.js 中拖动路径



我无法弄清楚如何使用 d3 在 svg 对象周围拖动路径.js

具体来说,我有一个正态分布形状渲染为 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 + ")");
}

下面是实现拖动的代码版本:

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>

相关内容

  • 没有找到相关文章

最新更新