D3.js d3动态气泡图-向气泡添加文本
我正在使用动态bubblechart创建一个可视化。但是我没有浮动的工具提示,我只想用它的名字来标记每个气泡,我尝试了许多不同的方法,但似乎无法使它工作。任何提示都将不胜感激D3.js d3动态气泡图-向气泡添加文本,d3.js,visualization,bubble-chart,D3.js,Visualization,Bubble Chart,我正在使用动态bubblechart创建一个可视化。但是我没有浮动的工具提示,我只想用它的名字来标记每个气泡,我尝试了许多不同的方法,但似乎无法使它工作。任何提示都将不胜感激 window.custom_bubble_chart = (function(d3, CustomTooltip) { //"use strict"; $("#tags").html(""); // Work out chart sizes var width = $("#tags").width();
window.custom_bubble_chart = (function(d3, CustomTooltip) {
//"use strict";
$("#tags").html("");
// Work out chart sizes
var width = $("#tags").width();
var height = $("#tags").height();
var tooltip = CustomTooltip("gates_tooltip", 180);
var layout_gravity = -0.01;
var damper = 0.1;
var nodes = [];
var vis, force, circles, radius_scale;
var center = {x: width / 2, y: height / 2};
var year_centers = {
"positive": {x: width / 3, y: height / 2},
"neutral": {x: width / 2, y: height / 2},
"negative": {x: 2 * width / 3, y: height / 2}
};
var fill_color = d3.scale.ordinal()
.domain(["low", "medium", "high"])
.range(["#99cc00", "#ff4444", "#33b5e5"]);
function custom_chart(data) {
var max_amount = d3.max(data, function(d) { return parseInt(d.freq, 10); } );
radius_scale = d3.scale.pow().exponent(0.5).domain([0, max_amount]).range([2, 25]);
//create node objects from original data
//that will serve as the data behind each
//bubble in the vis, then add each node
//to nodes to be used later
data.forEach(function(d){
var node = {
id: d.id,
radius: radius_scale(parseInt(d.freq, 4)),
value: d.freq,
name: d.word,
group: d.sentiment_adj,
year: d.sentiment_adj,
x: Math.random() * 900,
y: Math.random() * 800
};
nodes.push(node);
});
nodes.sort(function(a, b) {return b.value- a.value; });
vis = d3.select("#tags").append("svg")
.attr("width", width)
.attr("height", height)
.attr("id", "svg_tags");
circles = vis.selectAll("circle")
.data(nodes, function(d) { return d.id ;});
circles.enter().append("circle")
.attr("r", 0)
.attr("fill", function(d) { return fill_color(d.group) ;})
.attr("stroke-width", 2)
.attr("stroke", function(d) {return d3.rgb(fill_color(d.group)).darker();})
.attr("id", function(d) { return "bubble_" + d.id; })
.on("mouseover", function(d, i) {show_details(d, i, this);} )
.on("mouseout", function(d, i) {hide_details(d, i, this);} );
//fill circles with text - testing code that doesnt work!
//circles.append("text")
//.attr("text-anchor", "middle")
// .attr("dy", ".3em")
// .text(function(d) { return data.name ; });
circles.transition().duration(2000).attr("r", function(d) { return d.radius; });
}
function charge(d) {
return -Math.pow(d.radius, 2.0) / 8;
}
function start() {
force = d3.layout.force()
.nodes(nodes)
.size([width, height]);
}
function display_group_all() {
force.gravity(layout_gravity)
.charge(charge)
.friction(0.9)
.on("tick", function(e) {
circles.each(move_towards_center(e.alpha))
.attr("cx", function(d) {return d.x;})
.attr("cy", function(d) {return d.y;});
});
force.start();
hide_years();
}
function move_towards_center(alpha) {
return function(d) {
d.x = d.x + (center.x - d.x) * (damper + 0.02) * alpha;
d.y = d.y + (center.y - d.y) * (damper + 0.02) * alpha;
};
}
function display_by_year() {
force.gravity(layout_gravity)
.charge(charge)
.friction(0.9)
.on("tick", function(e) {
circles.each(move_towards_year(e.alpha))
.attr("cx", function(d) {return d.x;})
.attr("cy", function(d) {return d.y;});
});
force.start();
display_years();
}
function move_towards_year(alpha) {
return function(d) {
var target = year_centers[d.year];
d.x = d.x + (target.x - d.x) * (damper + 0.02) * alpha * 1.1;
d.y = d.y + (target.y - d.y) * (damper + 0.02) * alpha * 1.1;
};
}
function display_years() {
var years_x = {"Positive": width/3, "Neutral": width / 2, "Negative": width - width/3};
var years_data = d3.keys(years_x);
var years = vis.selectAll(".years")
.data(years_data);
years.enter().append("text")
.attr("class", "years")
.attr("x", function(d) { return years_x[d]; } )
.attr("y", 40)
.attr("text-anchor", "middle")
.text(function(d) { return d;});
}
function hide_years() {
var years = vis.selectAll(".years").remove();
}
function show_details(data, i, element) {
d3.select(element).attr("stroke", "black");
var content = "<span><b> " + data.name + "</b></span><br/>";
tooltip.showTooltip(content, d3.event);
}
function hide_details(data, i, element) {
d3.select(element).attr("stroke", function(d) { return d3.rgb(fill_color(d.group)).darker();} );
tooltip.hideTooltip();
}
var my_mod = {};
my_mod.init = function (_data) {
custom_chart(_data);
start();
};
my_mod.display_all = display_group_all;
my_mod.display_year = display_by_year;
my_mod.toggle_view = function(view_type) {
if (view_type == 'year') {
display_by_year();
} else {
display_group_all();
}
};
return my_mod;
})(d3, CustomTooltip);
window.custom\u bubble\u chart=(函数(d3,自定义工具提示){
//“严格使用”;
$(“#标记”).html(“”);
//计算图表大小
变量宽度=$(“#标记”).width();
变量高度=$(“#标记”).height();
变量工具提示=自定义工具提示(“盖茨工具提示”,180);
var布局_重力=-0.01;
var阻尼器=0.1;
var节点=[];
var-vis、力、圆、半径和刻度;
var-center={x:width/2,y:height/2};
var年_中心={
“正”:{x:width/3,y:height/2},
“中性”:{x:width/2,y:height/2},
“负片”:{x:2*宽度/3,y:高度/2}
};
var fill_color=d3.scale.ordinal()
.domain([“低”、“中”、“高”])
.范围([“#99cc00”、“#ff4444”、“#33b5e5”]);
功能自定义图表(数据){
var max_amount=d3.max(数据,函数(d){return parseInt(d.freq,10);});
radius_scale=d3.scale.pow().指数(0.5).域([0,max_amount]).范围([2,25]);
//从原始数据创建节点对象
//这将成为每一个问题背后的数据
//在vis中创建气泡,然后添加每个节点
//到稍后使用的节点
data.forEach(函数(d){
变量节点={
id:d.id,
半径:半径刻度(parseInt(d.freq,4)),
值:d.freq,
姓名:d.word,
组:d.情绪,
年份:d.情绪,
x:Math.random()*900,
y:Math.random()*800
};
nodes.push(节点);
});
sort(函数(a,b){返回b.value-a.value;});
vis=d3.选择(“#标记”).追加(“svg”)
.attr(“宽度”,宽度)
.attr(“高度”,高度)
.attr(“id”、“svg_标签”);
圆圈=相对于选择全部(“圆圈”)
.data(节点,函数(d){返回d.id;});
circles.enter().append(“圆”)
.attr(“r”,0)
.attr(“fill”,函数(d){return fill_color(d.group);})
.attr(“笔划宽度”,2)
.attr(“笔划”,函数(d){return d3.rgb(fill_color(d.group)).darker();})
.attr(“id”,函数(d){return“bubble_”+d.id;})
.on(“mouseover”,函数(d,i){show_details(d,i,this);})
.on(“mouseout”,函数(d,i){hide_details(d,i,this);});
//用不起作用的文本测试代码填充圆圈!
//圆。追加(“文本”)
//.attr(“文本锚定”、“中间”)
//.attr(“dy”,“.3em”)
//.text(函数(d){return data.name;});
circles.transition().duration(2000).attr(“r”,函数(d){返回d.radius;});
}
功能费(d){
返回-数学功率(d.radius,2.0)/8;
}
函数start(){
force=d3.layout.force()
.节点(节点)
.尺寸([宽度、高度]);
}
功能显示\u组\u全部(){
重力力(布局图+重力)
.收费
.摩擦力(0.9)
.on(“勾选”),功能(e){
圆。每个圆(向中心移动(e.alpha))
.attr(“cx”,函数(d){return d.x;})
.attr(“cy”,函数(d){返回d.y;});
});
force.start();
躲藏十年;
}
函数将_移向_中心(alpha){
返回函数(d){
d、 x=d.x+(中心x-d.x)*(阻尼器+0.02)*α;
d、 y=d.y+(中心y-d.y)*(阻尼器+0.02)*α;
};
}
功能按年份显示{
重力力(布局图+重力)
.收费
.摩擦力(0.9)
.on(“勾选”),功能(e){
圆圈。每一个(向第二年移动(e.alpha))
.attr(“cx”,函数(d){return d.x;})
.attr(“cy”,函数(d){返回d.y;});
});
force.start();
显示年份();
}
功能向年移动(α){
返回函数(d){
var目标=年/年中心[d.year];
d、 x=d.x+(target.x-d.x)*(阻尼器+0.02)*α*1.1;
d、 y=d.y+(target.y-d.y)*(阻尼器+0.02)*α*1.1;
};
}
功能显示(年){
var years_x={“正”:宽度/3,“中性”:宽度/2,“负”:宽度-宽度/3};
var年数=d3.键(年数x);
var年数=与选择的年数(“.年”)
.数据(年/年数据);
years.enter().append(“文本”)
.attr(“类别”、“年份”)
.attr(“x”,函数(d){return years_x[d];})
.attr(“y”,40)
.attr(“文本锚定”、“中间”)
.text(函数(d){return d;});
}
函数hide_years(){
var years=vis.selectAll(“.years”).remove();
}
函数显示详细信息(数据、i、元素){
d3.选择(元素).attr(“笔划”、“黑色”);
var content=“”+data.name+“
”;
工具提示.显示工具提示(内容,d3.事件);
}
函数隐藏_详细信息(数据、i、元素){
d3.select(element).attr(“stroke”,函数(d){返回d3.rgb(fill_color(d.group)).darker();});
工具提示;
}
var my_mod={};
my_mod.init=函数(_数据){
自定义图表(数据);
start();
};
my_mod.display_all=显示组_all;
my_mod.display_year=按年显示;
my_mod.toggle_view=函数(视图类型){
如果(视图类型=='年'){
按年显示年();
}否则{
显示_组_全部();
}
};
返回我的_mod;
})(d3,自定义工具提示);
不能在SVG中的形状中添加文本。文本元素需要单独定位
您有两个选择:
- 创建一个
元素的选择,并将数据连接到它们,完全与圆圈分开;或者 - 使加入数据的主选择由
元素组成,然后将圆圈和文本添加到组中李>
第二个选项使更新更容易,尽管您必须更改更新功能以使用变换进行定位,而不是使用
cx
和cy
。这是一个为每个节点使用组的方法,每个节点包含一个圆和一个标签。不能将文本元素附加到圆元素,因为圆元素不是容器。您将需要创建一个组元素(“g”)和appen