在气泡图上强制模拟文本不起作用
Force simulation of texts on bubble-chart does not work
我有一个脚本,我可以在其中制作圆圈,然后在上面附加文字。我想使用力模拟,这样不同圈子的文本就不会重叠。
我目前面临的问题如下图所示:(左边2个红圈有重叠文字)
我在文本脚本中使用了力模拟,但没有任何反应。我没有收到任何错误,但文本仍然重叠。我尝试了很多解决方案,但似乎没有任何效果。
以下是我的脚本:
function graph(data){
//var margin = {top: 30, right: 20, bottom: 30, left: 50}
var margin = 40,
width = 600,
height = 400;
// var force = d3.layout.force()
// .nodes(datas)
// .size([width, height]);
simulation = d3.forceSimulation()
.force("x", d3.forceX())
.force("y", d3.forceY())
.force("collide", d3.forceCollide(20));
var xscale = d3.scaleLinear()
.domain([0, d3.max(data, function (d) {
return +d.student_percentile;
})])
.nice()
.range([0, width]);
var yscale = d3.scaleLinear()
.domain([0, d3.max(data, function (d) {
return +d.rank;
})])
.nice()
.range([height, 0]);
var xAxis = d3.axisBottom().scale(xscale).tickFormat(function(d) {
return d > 100 ? "Not Available" : d
});
var yAxis = d3.axisLeft().scale(yscale);
var svg = d3.select('.chart')
.classed("svg-container", true)
.append('svg')
.attr('class', 'chart')
.attr("viewBox", "0 0 680 490")
.attr("preserveAspectRatio", "xMinYMin meet")
.classed("svg-content-responsive", true)
.append("g")
.attr("transform", "translate(" + margin + "," + margin + ")");
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
var color = d3.scaleOrdinal(d3.schemeCategory10);
var local = d3.local();
circles = svg.selectAll(null)
.data(data)
.enter()
.append("circle")
.attr("cx", width / 2)
.attr("cy", height / 2)
.attr("opacity", 0.3)
.attr("r", 20)
.style("fill", function(d){
if(+d.admit_probability <= 40){
return "red";
}
else if(+d.admit_probability > 40 && +d.admit_probability <= 75){
return "yellow";
}
else{
return "green";
}
})
.attr("cx", function(d) {
return xscale(+d.student_percentile);
})
.attr("cy", function(d) {
return yscale(+d.rank);
})
.on('mouseover', function(d, i) {
local.set(this, d3.select(this).style("fill"));
d3.select(this)
.transition()
.duration(1000)
.ease(d3.easeBounce)
.attr("r", 32)
.style("cursor", "pointer")
.attr("text-anchor", "middle");
var d = this.__data__;
show_details(d);
}
)
.on('mouseout', function(d, i) {
d3.select(this).style("fill", local.get(this));
d3.select(this).transition()
.style("opacity", 0.3)
.attr("r", 20)
.style("cursor", "default")
.transition()
.duration(1000)
.ease(d3.easeBounce);
remove_details();
});
texts = svg.selectAll(null)
.data(data)
.enter()
.append('text')
.attr("text-anchor", "middle")
.text(function(d) {
return d.abbreviation;
})
.attr("pointer-events", "none")
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.attr("fill", "black");
simulation.nodes(data).on("tick", function(){
texts.attr("x", function(d) {
return xscale(+d.student_percentile);
})
.attr("y", function(d) {
return yscale(+d.rank);
});
});
// force.on("tick", function() {
// texts.attr("x", function(d) { return +d.student_percentile; })
// .attr("y", function(d) { return +d.rank; });
// });
svg.append("text")
.attr("transform", "translate(" + (width / 2) + " ," + (height + margin) + ")")
.style("text-anchor", "middle")
.text("Percentile");
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Rank");
$('circle').tipsy({
gravity: 'w',
html: true,
title: function() {
var d = this.__data__;
return d.name + '<br/> Rank: ' + d.rank + '<br/> Admit Probaility: ' + d.admit_probability + '%';
}
});
}
我什至尝试过:
simulation.nodes(data).on("tick", function(){
texts.attr("x", d3.forceX().x(function(d) {
return xscale(+d.student_percentile);
}))
.attr("y", d3.forceY().y(function(d) {
return yscale(+d.rank);
}));
});
这也不行。
如果没有看到您的数据或最少 运行 代码,很难提供有效的答案。但是有些错误是显而易见的,这是一个通用的解决方案:
首先,您必须在 forceY
和 forceX
函数中指定文本的位置:
simulation = d3.forceSimulation()
.force("x", d3.forceX(function(d) {
return xscale(+d.student_percentile);
}))
.force("y", d3.forceY(function(d) {
return yscale(+d.rank);
}))
.force("collide", d3.forceCollide(20));
然后,在 tick
函数中,您只需使用模拟创建的 x
和 y
属性:
simulation.nodes(data).on("tick", function() {
texts.attr("x", function(d) {
return d.x;
})
.attr("y", function(d) {
return d.y;
});
});
我有一个脚本,我可以在其中制作圆圈,然后在上面附加文字。我想使用力模拟,这样不同圈子的文本就不会重叠。
我目前面临的问题如下图所示:(左边2个红圈有重叠文字)
我在文本脚本中使用了力模拟,但没有任何反应。我没有收到任何错误,但文本仍然重叠。我尝试了很多解决方案,但似乎没有任何效果。
以下是我的脚本:
function graph(data){
//var margin = {top: 30, right: 20, bottom: 30, left: 50}
var margin = 40,
width = 600,
height = 400;
// var force = d3.layout.force()
// .nodes(datas)
// .size([width, height]);
simulation = d3.forceSimulation()
.force("x", d3.forceX())
.force("y", d3.forceY())
.force("collide", d3.forceCollide(20));
var xscale = d3.scaleLinear()
.domain([0, d3.max(data, function (d) {
return +d.student_percentile;
})])
.nice()
.range([0, width]);
var yscale = d3.scaleLinear()
.domain([0, d3.max(data, function (d) {
return +d.rank;
})])
.nice()
.range([height, 0]);
var xAxis = d3.axisBottom().scale(xscale).tickFormat(function(d) {
return d > 100 ? "Not Available" : d
});
var yAxis = d3.axisLeft().scale(yscale);
var svg = d3.select('.chart')
.classed("svg-container", true)
.append('svg')
.attr('class', 'chart')
.attr("viewBox", "0 0 680 490")
.attr("preserveAspectRatio", "xMinYMin meet")
.classed("svg-content-responsive", true)
.append("g")
.attr("transform", "translate(" + margin + "," + margin + ")");
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
var color = d3.scaleOrdinal(d3.schemeCategory10);
var local = d3.local();
circles = svg.selectAll(null)
.data(data)
.enter()
.append("circle")
.attr("cx", width / 2)
.attr("cy", height / 2)
.attr("opacity", 0.3)
.attr("r", 20)
.style("fill", function(d){
if(+d.admit_probability <= 40){
return "red";
}
else if(+d.admit_probability > 40 && +d.admit_probability <= 75){
return "yellow";
}
else{
return "green";
}
})
.attr("cx", function(d) {
return xscale(+d.student_percentile);
})
.attr("cy", function(d) {
return yscale(+d.rank);
})
.on('mouseover', function(d, i) {
local.set(this, d3.select(this).style("fill"));
d3.select(this)
.transition()
.duration(1000)
.ease(d3.easeBounce)
.attr("r", 32)
.style("cursor", "pointer")
.attr("text-anchor", "middle");
var d = this.__data__;
show_details(d);
}
)
.on('mouseout', function(d, i) {
d3.select(this).style("fill", local.get(this));
d3.select(this).transition()
.style("opacity", 0.3)
.attr("r", 20)
.style("cursor", "default")
.transition()
.duration(1000)
.ease(d3.easeBounce);
remove_details();
});
texts = svg.selectAll(null)
.data(data)
.enter()
.append('text')
.attr("text-anchor", "middle")
.text(function(d) {
return d.abbreviation;
})
.attr("pointer-events", "none")
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.attr("fill", "black");
simulation.nodes(data).on("tick", function(){
texts.attr("x", function(d) {
return xscale(+d.student_percentile);
})
.attr("y", function(d) {
return yscale(+d.rank);
});
});
// force.on("tick", function() {
// texts.attr("x", function(d) { return +d.student_percentile; })
// .attr("y", function(d) { return +d.rank; });
// });
svg.append("text")
.attr("transform", "translate(" + (width / 2) + " ," + (height + margin) + ")")
.style("text-anchor", "middle")
.text("Percentile");
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Rank");
$('circle').tipsy({
gravity: 'w',
html: true,
title: function() {
var d = this.__data__;
return d.name + '<br/> Rank: ' + d.rank + '<br/> Admit Probaility: ' + d.admit_probability + '%';
}
});
}
我什至尝试过:
simulation.nodes(data).on("tick", function(){
texts.attr("x", d3.forceX().x(function(d) {
return xscale(+d.student_percentile);
}))
.attr("y", d3.forceY().y(function(d) {
return yscale(+d.rank);
}));
});
这也不行。
如果没有看到您的数据或最少 运行 代码,很难提供有效的答案。但是有些错误是显而易见的,这是一个通用的解决方案:
首先,您必须在 forceY
和 forceX
函数中指定文本的位置:
simulation = d3.forceSimulation()
.force("x", d3.forceX(function(d) {
return xscale(+d.student_percentile);
}))
.force("y", d3.forceY(function(d) {
return yscale(+d.rank);
}))
.force("collide", d3.forceCollide(20));
然后,在 tick
函数中,您只需使用模拟创建的 x
和 y
属性:
simulation.nodes(data).on("tick", function() {
texts.attr("x", function(d) {
return d.x;
})
.attr("y", function(d) {
return d.y;
});
});