简体   繁体   English

强制布局拖动,对象远离正确位置

[英]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函数处理xy位置。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM