[英]Force layout dragging, objects are far away from the correct position
So I am working on one of the class projects, which I have several data points associated with time, and the user can be able to drag the points if they overlap with each other. 因此,我正在一个班级项目中工作,该项目有几个与时间相关的数据点,并且用户可以拖动这些点(如果它们相互重叠)。
So the X-axis should be fixed to the date, and Y can change by dragging. 因此,X轴应固定为日期,并且Y可以通过拖动来更改。
Then I modified one of the examples on the internet. 然后,我修改了互联网上的示例之一。 And it seems somehow the circle and the text is not at the same position for the same object.
似乎在某种程度上,同一对象的圆和文本不在同一位置。
I am pretty sure this is because of the tick function 我很确定这是因为滴答功能
var ticked = function() {
node.attr("transform", function (d) {
return "translate(" + x(d.date) + "," + d.y + ")";
});
data= [ {id: "Object1", date: "2017-08-21", name: "Object1", count: .4, subtopics: []}, {id: "Object2", date: "2017-08-22", name: "Object2", count: 1, subtopics: []}, {id: "Object3", date: "2017-08-25", name: "Object3", count: 2, subtopics: []}, {id: "Object4", date: "2017-08-25", name: "Object4", count: 2, subtopics: []}, {id: "Object5", date: "2017-08-27", name: "Object5", count: 2, subtopics: []}, {id: "Object6", date: "2017-08-30", name: "Object6", count: 2, subtopics: []}, ] var r = d3.scaleSqrt() .domain([0, d3.max(data, function (d) { return d.count; })]) .range([0, 65]); var margin = {top: 20, right: 20, bottom: 100, left: 50}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var parseTime = d3.timeParse("%Y-%m-%d"); data.forEach(function(d) { d.date = parseTime(d.date); d.close = +d.close; }); var simulation = d3.forceSimulation() .force("charge", d3.forceManyBody().strength(-700).distanceMin(100).distanceMax(1000)) .force("link", d3.forceLink().id(function(d) { return d.index })) .force("center", d3.forceCenter(width / 2, height / 2)) .force("y", d3.forceY(0.001)) .force("x", d3.forceX(0.001)) var svg = d3.select('body').append('svg') .attr('width', width + margin.left + margin.right) .attr('height', height + margin.top + margin.bottom), g = svg.append('g') .attr('transform','translate(' + margin.left + ',' + margin.top + ')'); var formatNumber = d3.format(''); var x = d3.scaleTime() .range([0, width]); x.domain(d3.extent(data, function(d) { return d.date; })); svg.append("g") .attr("class", "axis") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x) .tickFormat(d3.timeFormat("%Y-%m-%d"))) var node = g.selectAll('.node') .data(data) .enter().append('g') .attr("class", "node") .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); node.append('circle') .attr('r', function(d) {return Math.max(16, r(d.count)); }) .attr("cx", function(d) { return x(d.date); }) .style("stroke", "Pink") .style("fill", "transparent"); node.append('text') .text(function(d){return d.name}) .attr("text-anchor", "middle"); var ticked = function() { node.attr("transform", function (d) { return "translate(" + x(d.date) + "," + dy + ")"; }); } simulation .nodes(data) .on("tick", ticked); function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d.fx = dx; d.fy = dy; } function dragged(d) { d.fy = d3.event.y; } function dragended(d) { if (!d3.event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; }
<!DOCTYPE html> <meta charset="utf-8"> <head> </head> <body style="margin:10px 0"> </div> <script src="https://d3js.org/d3.v4.min.js"></script> <script src="./scripts/main.js"></script> </body> </html>
So I try to use a different tick function with a different setup. 因此,我尝试在不同的设置中使用不同的刻度功能。 Like this, this time the circles are in the correct position, however, the text won't append to the Circle
像这样,这一次圆是在正确的位置,但是文本不会附加到圆上
data= [ {id: "Object1", date: "2017-08-21", name: "Object1", count: .4, subtopics: []}, {id: "Object2", date: "2017-08-22", name: "Object2", count: 1, subtopics: []}, {id: "Object3", date: "2017-08-25", name: "Object3", count: 2, subtopics: []}, {id: "Object4", date: "2017-08-25", name: "Object4", count: 2, subtopics: []}, {id: "Object5", date: "2017-08-27", name: "Object5", count: 2, subtopics: []}, {id: "Object6", date: "2017-08-30", name: "Object6", count: 2, subtopics: []}, ] var r = d3.scaleSqrt() .domain([0, d3.max(data, function (d) { return d.count; })]) .range([0, 65]); var margin = {top: 20, right: 20, bottom: 100, left: 50}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var parseTime = d3.timeParse("%Y-%m-%d"); data.forEach(function(d) { d.date = parseTime(d.date); d.close = +d.close; }); var simulation = d3.forceSimulation() .force("charge", d3.forceManyBody().strength(-700).distanceMin(100).distanceMax(1000)) .force("link", d3.forceLink().id(function(d) { return d.index })) .force("center", d3.forceCenter(width / 2, height / 2)) .force("y", d3.forceY(0.001)) .force("x", d3.forceX(0.001)) var svg = d3.select('body').append('svg') .attr('width', width + margin.left + margin.right) .attr('height', height + margin.top + margin.bottom), g = svg.append('g') .attr('transform','translate(' + margin.left + ',' + margin.top + ')'); var formatNumber = d3.format(''); var x = d3.scaleTime() .range([0, width]); x.domain(d3.extent(data, function(d) { return d.date; })); svg.append("g") .attr("class", "axis") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x) .tickFormat(d3.timeFormat("%Y-%m-%d"))) var node = g.selectAll('.node') .data(data) .enter().append('circle') .attr("class", "node") .attr('r', function(d) {return Math.max(16, r(d.count)); }) .attr("cx", function(d) { return x(d.date); }) .style("stroke", "Pink") .style("fill", "transparent") .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); var text = node.append("text") .text(function(d){return d.name}) .attr("x", function(d) { return x(d.date); }) .attr("text-anchor", "middle"); var ticked = function() { node .attr("cx", function(d) { return x(d.date); }) .attr("cy", function(d) { return dy; }); } simulation .nodes(data) .on("tick", ticked); function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d.fy = dy; } function dragged(d) { d.fy = d3.event.y; } function dragended(d) { if (!d3.event.active) simulation.alphaTarget(0); d.fy = null; }
<!DOCTYPE html> <meta charset="utf-8"> <body style="margin:10px 0"> </div> <script src="https://d3js.org/d3.v4.min.js"></script> <script src="./scripts/main.js"></script> </body> </html>
In your first code you're applying the x
position to the circles: 在您的第一个代码中,您将
x
位置应用于圆:
.attr("cx", function(d) {
return x(d.date);
})
Don't do that: the tick
function deals with the x
and y
positions. 不要那样做:
tick
函数处理x
和y
位置。
Here is your code removing that line: 这是删除该行的代码:
data= [ {id: "Object1", date: "2017-08-21", name: "Object1", count: .4, subtopics: []}, {id: "Object2", date: "2017-08-22", name: "Object2", count: 1, subtopics: []}, {id: "Object3", date: "2017-08-25", name: "Object3", count: 2, subtopics: []}, {id: "Object4", date: "2017-08-25", name: "Object4", count: 2, subtopics: []}, {id: "Object5", date: "2017-08-27", name: "Object5", count: 2, subtopics: []}, {id: "Object6", date: "2017-08-30", name: "Object6", count: 2, subtopics: []}, ] var r = d3.scaleSqrt() .domain([0, d3.max(data, function (d) { return d.count; })]) .range([0, 65]); var margin = {top: 20, right: 20, bottom: 100, left: 50}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var parseTime = d3.timeParse("%Y-%m-%d"); data.forEach(function(d) { d.date = parseTime(d.date); d.close = +d.close; }); var simulation = d3.forceSimulation() .force("charge", d3.forceManyBody().strength(-700).distanceMin(100).distanceMax(1000)) .force("link", d3.forceLink().id(function(d) { return d.index })) .force("center", d3.forceCenter(width / 2, height / 2)) .force("y", d3.forceY(0.001)) .force("x", d3.forceX(0.001)) var svg = d3.select('body').append('svg') .attr('width', width + margin.left + margin.right) .attr('height', height + margin.top + margin.bottom), g = svg.append('g') .attr('transform','translate(' + margin.left + ',' + margin.top + ')'); var formatNumber = d3.format(''); var x = d3.scaleTime() .range([0, width]); x.domain(d3.extent(data, function(d) { return d.date; })); svg.append("g") .attr("class", "axis") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x) .tickFormat(d3.timeFormat("%Y-%m-%d"))) var node = g.selectAll('.node') .data(data) .enter().append('g') .attr("class", "node") .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); node.append('circle') .attr('r', function(d) {return Math.max(16, r(d.count)); }) .style("stroke", "Pink") .style("fill", "transparent"); node.append('text') .text(function(d){return d.name}) .attr("text-anchor", "middle") .attr("pointer-events", "none"); var ticked = function() { node.attr("transform", function (d) { return "translate(" + x(d.date) + "," + dy + ")"; }); } simulation .nodes(data) .on("tick", ticked); function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d.fx = dx; d.fy = dy; } function dragged(d) { d.fy = d3.event.y; } function dragended(d) { if (!d3.event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; }
<!DOCTYPE html> <meta charset="utf-8"> <head> </head> <body style="margin:10px 0"> </div> <script src="https://d3js.org/d3.v4.min.js"></script> <script src="./scripts/main.js"></script> </body> </html>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.