javascript - d3.js 向条形图添加第二个标签
问题描述
2部分问题:
我有一个使用多个数组创建的条形图。这些数组包含棒球队的获胜百分比;相关的球队颜色;和他们的名字。
我可以在图表上创建一组标签,名称或获胜百分比。但是我不能同时上两个。见下文。
我正在使用的代码是:
let WinsLabel = svgContainer.selectAll("text")
.data(d3.zip(TeamArray, WinPercArray, Colours));
WinsLabel.enter()
.append("text")
.attr("fill", "black")
.attr("x", function(d, i) {
return 45 + (i * 50);
})
.attr("y", 700)
.transition()
.duration(1000)
.attr("x", function(d,i){
return 70 + (i*50);
})
.attr("y", function(d){
return 685 - d[1];
})
.attr("text-anchor","middle")
.attr("font-family", "sans-serif")
.attr("font-size", "15px")
.attr("fill", "black")
.text(function(d){
return d[1]/10 + "%";
});
let TeamLabel = svgContainer.selectAll("text")
.data(d3.zip(TeamArray, WinPercArray, Colours));
TeamLabel.enter()
.append("text")
.attr("fill", "black")
.attr("x", function(d, i) {
return 45 + (i * 50);
})
.attr("y", 700)
.transition()
.duration(1000)
.attr("x", function(d,i){
return 70 + (i*50);
})
.attr("y", function(d){
return 700 - d[1]/2;
})
.attr("text-anchor","middle")
.attr("font-family", "sans-serif")
.attr("font-size", "15px")
.attr("fill", "white")
.text(function(d){
return d[0];
});
当我使用两个脚本运行代码时,只显示 win %,但名称不显示。为了让名字出现,我必须删除第一个标签。
我的问题的两个部分是:
- 如何让两组标签同时显示?
- 如何让名称在矩形/条中垂直排列?
解决方案
D3 代表数据驱动的东西;它的核心原则是基于链接元素/选择,与数据。当您设置数据时,( var selection = selectAll(...).data(...)
),您需要考虑 3 种情况:
- 一些现有元素可以链接到新数据中的某些项目。您使用它们访问它们
selection
- 某些元素无法链接到新数据中的任何项目。您使用它们访问它们
selection.exit()
- 新数据中的某些项目无法链接到选择中的任何元素。您通过使用访问它们
selection.enter()
在最简单的情况下,数据和元素之间的链接是通过索引进行的——即选择中的第一个元素与数据数组中的第一项链接,第二个与第二个链接,依此类推。.enter()
当且仅当(在此按索引上下文中)该数据项的索引大于选择的大小时,d3 无法找到数据项的元素(= 被放入选择中)。
在您最初的选择中
let WinsLabel = svgContainer.selectAll("text")
.data(d3.zip(TeamArray, WinPercArray, Colours));
选择是空的,因为还没有文本标签。由于它是空的,所有要创建的占位符都在.enter()
选择范围内。但是,在您下次选择其他标签类型时
let TeamLabel = svgContainer.selectAll("text")
.data(d3.zip(TeamArray, WinPercArray, Colours));
选择是传递数据的大小,因此.enter()
选择是空的;它TeamLabel
是包含所有旧元素(百分比标签text
标签)的选择,但它们重新分配了它们的数据值。
Andrew 提出了一种分配类的解决方案,但我个人会将与同一团队相关的所有元素放在一个组中。
var TeamArray = ["Yankees", "Rays", "RedSox", "Jays","Orioles", "Twin", "Indians", "WhiteSox", "Detroit", "Royals", "Astros", "Rangers", "A's", "Angels","Mariners"];
var WinPercArray = [653, 609, 540, 400, 300, 667, 521, 458, 383, 347, 660, 511, 500, 458, 442];
var Colours = ["#003087", "#092C5C", "#BD3039", "#134A8E", "#DF4601", "#002B5C", "#0C2340", "#C4CED4", "#FA4616", "#BD9B60", "#EB6E1F", "#C0111F", "#003831", "#003263", "#005C5C"];
var data = d3.zip(TeamArray, WinPercArray, Colours);
var svg = d3.select('body').append('svg').attr('height', 300).attr('width', 800);
var teams = svg.selectAll('g.teams')
.data(data);
var scale = d3.scaleLinear()
.domain([0, 1000])
.range([200, 0]);
var teamsEnter = teams.enter()
.append('g')
.classed('team', true)
.attr('transform', function(d, i){
return 'translate(' + (i*50) + ',0)';
})
teamsEnter.append('rect')
.attr('width', 50)
.attr('y', function(d) { return scale(d[1]); })
.attr('height', function(d) { return scale(0) - scale(d[1]); })
.style('fill', function(d) { return d[2]; });
teamsEnter.append('text')
.attr('x', 25)
.attr('y', function(d) { return scale(d[1]) - 30; })
.text(function(d){ return d[0]; });
teamsEnter.append('text')
.attr('x', 25)
.attr('y', function(d) { return scale(d[1]) - 15; })
.text(function(d){ return d[1]; });
text {
text-anchor: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
组以某种方式充当内部项目的封装,因此您可以在精神上将数据绑定到组(即何时创建/更新/删除它)与使用其子项时发生的实际逻辑分开
推荐阅读
- appium - 无法使用 UiScrollable 和 TouchActions 在 Appium 中水平滚动
- css - 在已经使用 withTheme() 的同时使用 withStyles() 覆盖 Material-ui 主题
- google-apps-script - 不同用户的脚本锁定谷歌应用程序制造商
- react-native - React Native 新架构 - Redux & Hooks
- assembly - 如何使用浮点寄存器计算平方根
- ios - 如何测试在视图控制器单元测试中设置私有变量的方法?
- docker - 如何在一个 CircleCI 配置中进行两个构建?
- ruby-on-rails - 在 MacOS 上安装 therubyracer 时未定义的局部变量或方法“make”
- spring - 带有 OAuth2 的 Spring Security 5 休息客户端
- arraylist - 为什么我的数字序列不能正确地从二维数组列表中打印出来?