d3.js - D3 条形图,其中轴标签是数据的超链接
问题描述
我试图让水平条形图上的 y 轴链接成为基于数据值的超链接。而且我无法让它工作,而且我找不到它已经完成的例子。
任何示例或建议将不胜感激。
我的代码是:
function dohorizontalbarchartD3(data, elementid, topic, topicscore, width, height, margin)
{
var y = d3.scaleBand().range([height, 0]).padding(0.1);
var x = d3.scaleLinear().range([0, width]);
var svg = d3.select(elementid).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("fill", "steelblue")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Scale the range of the data in the domains
x.domain([0, d3.max(data, function(d){ return d[topicscore]; })])
y.domain(data.map(function(d) { return d[topic]; }));
// append the rectangles for the bar chart
var bars = svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("width", function(d) {return x(d[topicscore]); } )
.attr("y", function(d) { return y(d[topic]); })
.attr("height", y.bandwidth())
// add the x Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the y Axis
svg.append("g")
.call(d3.axisLeft(y))
.style("cursor", "pointer")
.on("click", function(d) {window.location.href = "signal.html?id=" + d["id"];});
}
var data = [{topic: "disaster management", weight: 5.044282881692003, "id": 10}, {topic: "analytics", weight: 5.111022997620935, "id": 11}, {topic: "systems management", weight: 5.255783212161269, "id": 12}, {topic: "human resources", weight: 5.420123698898777, "id": 13}, {topic: "machine learning", weight: 6.357388316151202, "id": 14}, {topic: "automation", weight: 6.579434311393074, "id": 15}, {topic: "health and safety", weight: 7.607482274852919, "id": 16}, {topic: "cost control", weight: 7.876784769962982, "id": 17}, {topic: "climate change", weight: 8.24345757335448, "id": 18}, {topic: "inventory management", weight: 8.511369645690111, "id": 19}, {topic: "transformation", weight: 8.650363516192993, "id": 20}, {topic: "supply chain", weight: 8.916204070843246, "id": 21}, {topic: "water treatment", weight: 9.996866186148543, "id": 22}];
var margin = {top: 10, right: 20, bottom: 30, left: 200};
dohorizontalbarchartD3(data, "#scoutblock1", "topic", "weight", 300, 500, margin);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<body>
<div id="scoutblock1"></div>
</body>
</html>
解决方案
你快到了!
让我们看看您尝试附加链接的代码行:
// add the y Axis
svg.append("g")
.call(d3.axisLeft(y))
.style("cursor", "pointer")
.on("click", function(d) {window.location.href = "signal.html?id=" + d["id"];});
使用selection.call(d3.axisLeft(y))
d3 添加一个轴,该轴首先是轴线的一个path
元素,也就是每个标签的刻度线,在各自的位置有一条微小的正交线。像很多时候一样,元素检查器是您的朋友,我鼓励您在浏览器中打开它并查看 DOM 中生成的元素。
这一切都按预期工作,但是,您当前所指的选择没有附加任何数据。同样,让我们使用检查器查看属性,您看不到任何__data__
属性:
这意味着,您在.on("click", function(d)...)
回调函数中对数据的引用将始终undefined
具有d
.
d3 所做的是它创建了记号作为子节点,并且数据分别附加到每个记号。因此,您必须做的一件事是.on("click", function(d)...)
为每个刻度调用。
这是一种方法:
// add the y Axis
svg.append("g")
.attr("class", "y axis") // assign a class, so we can reference it below
.call(d3.axisLeft(y));
svg.select(".y.axis") // select the g element with the y axis
.selectAll(".tick") // select all ticks of the axis and do for each:
.style("cursor", "pointer")
.on("click", function(d) {
// your callback
});
现在我们有了逻辑,我们要调用超链接。附加到每个刻度的数据基于我们提供给的数据d3.axisLeft()
,即y
。鉴于我们选择的y
函数,每个刻度都包含每个数据元素的主题字符串。让我们再用元素检查器来确认一下:
这意味着到目前为止,我们无法访问回调函数中的 id 属性,因为每个刻度的数据只包含数据的主题字符串。
我们注意到有两个单独的要求:
- 一方面,主题字符串是我们希望轴显示为标签的内容。
- 另一方面,我们想引用id属性来调用超链接。
有很多方法可以做到,为了在回调函数中保留后一个要求,我们可以这样做:
svg.select(".y.axis")
.selectAll(".tick")
.style("cursor", "pointer")
.on("click", function(d) {
var id = data.find(function(ele) { return ele.topic === d;}).id;
window.location.href = "signal.html?id=" + id;
});
回想一下,d
每个刻度元素中的数据仅引用相应的主题字符串。所以我们可以遍历原始数据来找到第一个包含主题的对象d
。对于那个对象,我们想要拥有 id 属性。
这是完整的代码(我稍微更改了您的 html 代码以符合惯例):
var data = [{topic: "disaster management", weight: 5.044282881692003, "id": 10}, {topic: "analytics", weight: 5.111022997620935, "id": 11}, {topic: "systems management", weight: 5.255783212161269, "id": 12}, {topic: "human resources", weight: 5.420123698898777, "id": 13}, {topic: "machine learning", weight: 6.357388316151202, "id": 14}, {topic: "automation", weight: 6.579434311393074, "id": 15}, {topic: "health and safety", weight: 7.607482274852919, "id": 16}, {topic: "cost control", weight: 7.876784769962982, "id": 17}, {topic: "climate change", weight: 8.24345757335448, "id": 18}, {topic: "inventory management", weight: 8.511369645690111, "id": 19}, {topic: "transformation", weight: 8.650363516192993, "id": 20}, {topic: "supply chain", weight: 8.916204070843246, "id": 21}, {topic: "water treatment", weight: 9.996866186148543, "id": 22}];
var margin = {top: 10, right: 20, bottom: 30, left: 200};
dohorizontalbarchartD3(data, "#scoutblock1", "topic", "weight", 300, 500, margin);
function dohorizontalbarchartD3(data, elementid, topic, topicscore, width, height, margin) {
var y = d3.scaleBand().range([height, 0]).padding(0.1);
var x = d3.scaleLinear().range([0, width]);
var svg = d3.select(elementid).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("fill", "steelblue")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Scale the range of the data in the domains
x.domain([0, d3.max(data, function(d){ return d[topicscore]; })])
y.domain(data.map(function(d) { return d[topic]; }));
// append the rectangles for the bar chart
var bars = svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("width", function(d) {return x(d[topicscore]); } )
.attr("y", function(d) { return y(d[topic]); })
.attr("height", y.bandwidth())
// add the x Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the y Axis
svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(y));
svg.select(".y.axis")
.selectAll(".tick")
.style("cursor", "pointer")
.on("click", function(d) {
var id = data.find(function(ele) { return ele.topic === d;}).id;
window.location.href = "signal.html?id=" + id;
});
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>title</title>
<!--link rel="stylesheet" href="style.css"-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
</head>
<body>
<div id="scoutblock1"></div>
推荐阅读
- javascript - 如何制作出现在滚动条上的导航栏?
- docker - 获取 https://registry-1.docker.io/v2/:拨打 tcp 34.201.236.93:443:连接:连接被拒绝
- reactjs - 日期范围滑块未在 react-google-charts 中呈现
- google-cloud-platform - 承诺使用成本高于非承诺使用 Kubernetes Engine
- mysql - 在 GROUP BY 中使用 LIMIT 两次获得每组 N 个结果
- c++ - 带有链表的奇怪段错误
- json - Flutter - 访问 JSON 存储的图像并在列表视图中显示
- capistrano - capistrano-resque 在启动期间失败
- android - Android Studio Layout Editor 显示不正确
- android - 当我尝试在其上保存信息时,json arrayList 出现问题