javascript d3.js / svg - 如何动态地将文本附加到我的弧
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14172343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
d3.js / svg - how to dynamically append text to my arcs
提问by mheavers
I am trying to complete the last bit of a d3 project which dynamically creates these blue arcs, over which I need to place arc text, as shown in this image:
我正在尝试完成动态创建这些蓝色弧线的 d3 项目的最后一点,我需要在其上放置弧线文本,如下图所示:
The image above is something I've done by placing the arc text statically, through trial and error, but I want to place it dynamically, based on the blue arcs which sit beneath the text. This is the code that dynamically creates the arcs:
上图是我通过反复试验静态放置圆弧文本所做的事情,但我想根据位于文本下方的蓝色圆弧动态放置它。这是动态创建弧的代码:
var groupData = data_group.selectAll("g.group")
.data(nodes.filter(function(d) { console.log(d.__data__.key); return (d.key=='Employers' ||{exp:channel:entries category="13" backspace="2"} d.key == '{url_title}' ||{/exp:channel:entries}) && d.children; }))
.enter().append("group")
.attr("class", "group");
arc_group.selectAll("g.arc")
.data(groupData[0])
.enter().append("svg:path")
.attr("d", groupArc)
.attr("class", "groupArc")
.style("fill", "#1f77b4")
.style("fill-opacity", 0.5);
The {exp:} content is preparsed data I'm pulling from my content management system in expression engine if it looks confusing.
{exp:} 内容是我从表达式引擎中的内容管理系统中提取的预解析数据,如果它看起来令人困惑。
So, I have my arcs. Now you'll notice in the groupData code block I have a console.log statement, that will give me the names I want to appear in the arc text:
所以,我有我的弧线。现在你会注意到在 groupData 代码块中我有一个 console.log 语句,它会给我我想要出现在弧文本中的名字:
console.log(d.__data__.key);
Now, the code I was using to place the arc text statically was this:
现在,我用来静态放置圆弧文本的代码是这样的:
var arcData = [
{aS: 0, aE: 45,rI:radius - chartConfig.linePadding + chartConfig.arcPadding,rO:radius - chartConfig.linePadding + chartConfig.textPadding-chartConfig.arcPadding}
];
var arcJobsData = d3.svg.arc().innerRadius(arcData[0].rI).outerRadius(arcData[0].rO).startAngle(degToRad(1)).endAngle(degToRad(15));
var g = d3.select(".chart").append("svg:g").attr("class","arcs");
var arcJobs = d3.select(".arcs").append("svg:path").attr("d",arcJobsData).attr("id","arcJobs").attr("class","arc");
g.append("svg:text").attr("x",3).attr("dy",15).append("svg:textPath").attr("xlink:href","#arcJobs").text("JOBS").attr("class","arcText"); //x shifts x pixels from the starting point of the arc. dy shifts the text y units from the top of the arc
And in this above code, the only thing left that I should need to do is dynamically assign an ID to the arcs, and then reference that ID in the xlink:href attribute, as well as replace the text("JOBS") with text that pulls from d.data__key. Given the code above which dynamically creates the arcs, and given that I know how to dynamically create and retrieve the text I want to place in the arcs using d.__data.key, I should be able to finish this thing off, but I can't figure out how write code in d3 that will take the data and place it in the arcs. Can anybody help with this?
在上面的代码中,我唯一需要做的就是为弧动态分配一个 ID,然后在 xlink:href 属性中引用该 ID,并将文本(“JOBS”)替换为文本从 d 拉。数据__键。鉴于上面动态创建弧的代码,并且我知道如何使用 d.__data.key动态创建和检索我想要放置在弧中的文本,我应该能够完成这件事,但我可以不知道如何在 d3 中编写代码来获取数据并将其放置在弧中。有人可以帮忙吗?
采纳答案by mheavers
Figured this out. Changed the structure of things a bit so it made a little more sense, but essentially what I did is this:
想通了这一点。稍微改变了事物的结构,使其更有意义,但基本上我所做的是:
var groupData = data_group.selectAll("g.group")
.data(nodes.filter(function(d) { return (d.key=='Employers' ||{exp:channel:entries category="13" backspace="2"} d.key == '{url_title}' ||{/exp:channel:entries}) && d.children; }))
.enter().append("group")
.attr("class", "group"); //MH - why do we need this group - these elements are empty. Shouldn't this just be an array? Find out how to delete the svg elements without getting rid of the data, which is needed below.
var groupArc = d3.svg.arc()
.innerRadius(ry - 177)
.outerRadius(ry - 157)
.startAngle(function(d) { return (findStartAngle(d.__data__.children)-2) * pi / 180;})
.endAngle(function(d) { console.log(d.__data__.key); return (findEndAngle(d.__data__.children)+2) * pi / 180});
var arc_and_text = arc_group.selectAll("g.arc")
.data(groupData[0])
.enter().append("svg:g")
.attr("class","arc_and_text");
var arc_path = arc_and_text.append("svg:path")
.attr("d", groupArc)
.attr("class", "groupArc")
.attr("id", function(d, i) { return "arc" + i; })
.style("fill", "#1f77b4")
.style("fill-opacity", 0.5); //MH: (d.__data__.key) gives names of groupings
var arc_text = arc_and_text.append("text")
.attr("class","arc_text")
.attr("x", 3)
.attr("dy", 15);
arc_text.append("textPath")
.attr("xlink:href", function(d, i) { return "#arc" + i; })
.attr("class","arc_text_path")
.style("fill","#ffffff")
.text(function(d, i) { return d.__data__.key; });
D3 still mystifies me a bit, and I'm sure this code could be much improved, but it works.
D3 仍然让我有些困惑,我确信这段代码可以大大改进,但它确实有效。
回答by seliopou
You should give this blog post on nested selectionsa read; I believe it'll explain what you're trying to do.
你应该阅读这篇关于嵌套选择的博客文章;我相信它会解释你想要做什么。
Here's the gist. When you add data to your selection, assign the selection to a variable:
这是要点。将数据添加到选择时,将选择分配给变量:
var g = data_group.selectAll("g.group")
.data(nodes.filter(function(d) { /* stuff */ }));
That way, you can perform subselections on it, which will receive a single element of the data bound to your g
selection. You can use this to add your arcs and text:
这样,您可以对其执行子选择,这将接收绑定到您的g
选择的数据的单个元素。您可以使用它来添加弧线和文本:
g.enter().append('group') // Question: Are you sure you mean 'group' here?
.attr('class', 'group')
g.selectAll('g.arc')
.data(function(d, i) { return d; })
enter().append('path')
// Setup the path here
g.selectAll('text')
.data(function(d, i) { return d; })
.enter().append('text')
.attr('text', function(d) { return d.__data__.key })
The functions that are being used to do data binding in the nested selections (i.e., the g.selectAll()
s) are being passed a single elementof the data attached to g
as d
, and i
is its index.
用于在嵌套选择(即g.selectAll()
s)中进行数据绑定的函数正在传递一个附加到as的数据元素,并且是它的索引。g
d
i