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

时间:2018-04-11 22:49:34

标签: javascript html css d3.js

所以我正在研究一个类项目,我有几个与时间相关的数据点,如果它们相互重叠,用户可以拖动它们。

因此,X轴应固定为日期,Y可以通过拖动来改变。

然后我修改了互联网上的一个例子。并且似乎某种程度上圆圈和文本不在同一个对象的相同位置。

我很确定这是因为滴答功能

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) + "," + d.y + ")";
    });
}         
    
simulation
    .nodes(data)
    .on("tick", ticked);

function dragstarted(d) {
    if (!d3.event.active) simulation.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
}
        
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>
&#13;
&#13;
&#13;

所以我尝试使用不同的滴答功能和不同的设置。像这样,这次圆圈处于正确的位置,然而,文字不会附加到圆圈

&#13;
&#13;
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 d.y; });
}         
    
simulation
    .nodes(data)
    .on("tick", ticked);

function dragstarted(d) {
    if (!d3.event.active) simulation.alphaTarget(0.3).restart();
        d.fy = d.y;
}
        
function dragged(d) {
        d.fy = d3.event.y;
}
        
function dragended(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
        d.fy = null;
}
&#13;
<!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>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:2)

在您的第一个代码中,您将x位置应用于圈子:

.attr("cx", function(d) { 
    return x(d.date); 
})

请勿这样做:tick功能处理xy位置。

以下是删除该行的代码:

&#13;
&#13;
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) + "," + d.y + ")";
    });
}         
    
simulation
    .nodes(data)
    .on("tick", ticked);

function dragstarted(d) {
    if (!d3.event.active) simulation.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
}
        
function dragged(d) {
        d.fy = d3.event.y;
}
        
function dragended(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
        d.fx = null;
        d.fy = null;
}
&#13;
<!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>
&#13;
&#13;
&#13;