如何将工具提示添加到 d3.js 路径?
How to add a tooltip to a d3.js path?
我正在使用 d3.js 拓扑和 d3.js 路径从 geojson 数据构建平面图。为了澄清起见,我还使用了 vue.js。我想在用户将鼠标悬停在房间上时添加工具提示(又名 d3.js 路径)。首先,当用户将鼠标悬停在路径上时,我只添加了一个控制台日志,但那没有用。我注意到,每次我加载应用程序时,它都会执行控制台日志,但不会在用户单击/悬停在 d3.js 路径上时执行。我听到有人说我必须创建一个不可见的圆形或矩形,将工具提示 属性 绑定到它,但我不认为一旦平面图变得复杂,该路线就不会起作用。我现在不关心向工具提示添加任何实际数据,但稍后我会想要。有人可以指出我正确的方向吗?谢谢。
const data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
0, 0
],
[
0, 11.4
],
[
7, 11.4
],
[
7, 0
],
[
0, 0
]
]
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
7, 0
],
[
7, 11.4
],
[
12, 11.4
],
[
12, 0
],
[
7, 0
]
]
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
12, 0
],
[
12, 11.4
],
[
19, 11.4
],
[
19, 0
],
[
12, 0
]
]
]
}
}
]
};
var svg = d3.select("svg")
var width = +svg.attr("width")
var height = +svg.attr("height")
svg.attr("transform", "translate(" + width / 2 + ",0)")
var projection = d3.geoIdentity().fitSize([width, height], data)
var path = d3.geoPath(projection)
svg.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", "grey")
.attr("fill-opacity", .2)
.attr("stroke", "black")
.attr("stroke-width", 1.5)
.on("mouseover", console.log("hello"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="200"></svg>
有几种方法可以做到这一点。最简单但也是最有限的方法是在每个 path
中创建一个 <title>
element。它会在悬停时显示,因为它是浏览器原生的。
const data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": { "name": "Kitchen" },
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
0, 0
],
[
0, 11.4
],
[
7, 11.4
],
[
7, 0
],
[
0, 0
]
]
]
}
},
{
"type": "Feature",
"properties": { "name": "Living room" },
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
7, 0
],
[
7, 11.4
],
[
12, 11.4
],
[
12, 0
],
[
7, 0
]
]
]
}
},
{
"type": "Feature",
"properties": { "name": "Toilet" },
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
12, 0
],
[
12, 11.4
],
[
19, 11.4
],
[
19, 0
],
[
12, 0
]
]
]
}
}
]
};
var svg = d3.select("svg")
var width = +svg.attr("width")
var height = +svg.attr("height")
svg.attr("transform", "translate(" + width / 2 + ",0)")
var projection = d3.geoIdentity().fitSize([width, height], data)
var path = d3.geoPath(projection)
svg.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", "grey")
.attr("fill-opacity", .2)
.attr("stroke", "black")
.attr("stroke-width", 1.5)
.append("title")
// Do this to maintain access to the features you drew
.datum(function(d) { return d; })
.text(function(d) {
return d.properties.name;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="200"></svg>
更复杂的可以使用绝对定位div
,例如:
const data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"name": "Kitchen"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
0, 0
],
[
0, 11.4
],
[
7, 11.4
],
[
7, 0
],
[
0, 0
]
]
]
}
},
{
"type": "Feature",
"properties": {
"name": "Living room"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
7, 0
],
[
7, 11.4
],
[
12, 11.4
],
[
12, 0
],
[
7, 0
]
]
]
}
},
{
"type": "Feature",
"properties": {
"name": "Toilet"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
12, 0
],
[
12, 11.4
],
[
19, 11.4
],
[
19, 0
],
[
12, 0
]
]
]
}
}
]
};
var svg = d3.select("svg")
var width = +svg.attr("width")
var height = +svg.attr("height")
var tooltip = d3.select("#tooltip")
svg.attr("transform", "translate(" + width / 2 + ",0)")
var projection = d3.geoIdentity().fitSize([width, height], data)
var path = d3.geoPath(projection)
svg.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", "grey")
.attr("fill-opacity", .2)
.attr("stroke", "black")
.attr("stroke-width", 1.5)
.on("mousemove", function(d) {
// +3 as some offset to make sure spawning the tooltip doesn't
// accidentally also cause unhover and thus removing itself
tooltip
.html(d.properties.name)
.style("display", "block")
.style("left", d3.event.x + 3 + 'px')
.style("top", d3.event.y + 3 + 'px');
})
.on("mouseleave", function() {
tooltip
.style("display", null)
.style("left", null)
.style("top", null);
});
#tooltip {
position: absolute;
top: 0;
left: 0;
display: none;
border: solid 1px red;
padding: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="200"></svg>
<div id="tooltip"></div>
我正在使用 d3.js 拓扑和 d3.js 路径从 geojson 数据构建平面图。为了澄清起见,我还使用了 vue.js。我想在用户将鼠标悬停在房间上时添加工具提示(又名 d3.js 路径)。首先,当用户将鼠标悬停在路径上时,我只添加了一个控制台日志,但那没有用。我注意到,每次我加载应用程序时,它都会执行控制台日志,但不会在用户单击/悬停在 d3.js 路径上时执行。我听到有人说我必须创建一个不可见的圆形或矩形,将工具提示 属性 绑定到它,但我不认为一旦平面图变得复杂,该路线就不会起作用。我现在不关心向工具提示添加任何实际数据,但稍后我会想要。有人可以指出我正确的方向吗?谢谢。
const data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
0, 0
],
[
0, 11.4
],
[
7, 11.4
],
[
7, 0
],
[
0, 0
]
]
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
7, 0
],
[
7, 11.4
],
[
12, 11.4
],
[
12, 0
],
[
7, 0
]
]
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
12, 0
],
[
12, 11.4
],
[
19, 11.4
],
[
19, 0
],
[
12, 0
]
]
]
}
}
]
};
var svg = d3.select("svg")
var width = +svg.attr("width")
var height = +svg.attr("height")
svg.attr("transform", "translate(" + width / 2 + ",0)")
var projection = d3.geoIdentity().fitSize([width, height], data)
var path = d3.geoPath(projection)
svg.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", "grey")
.attr("fill-opacity", .2)
.attr("stroke", "black")
.attr("stroke-width", 1.5)
.on("mouseover", console.log("hello"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="200"></svg>
有几种方法可以做到这一点。最简单但也是最有限的方法是在每个 path
中创建一个 <title>
element。它会在悬停时显示,因为它是浏览器原生的。
const data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": { "name": "Kitchen" },
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
0, 0
],
[
0, 11.4
],
[
7, 11.4
],
[
7, 0
],
[
0, 0
]
]
]
}
},
{
"type": "Feature",
"properties": { "name": "Living room" },
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
7, 0
],
[
7, 11.4
],
[
12, 11.4
],
[
12, 0
],
[
7, 0
]
]
]
}
},
{
"type": "Feature",
"properties": { "name": "Toilet" },
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
12, 0
],
[
12, 11.4
],
[
19, 11.4
],
[
19, 0
],
[
12, 0
]
]
]
}
}
]
};
var svg = d3.select("svg")
var width = +svg.attr("width")
var height = +svg.attr("height")
svg.attr("transform", "translate(" + width / 2 + ",0)")
var projection = d3.geoIdentity().fitSize([width, height], data)
var path = d3.geoPath(projection)
svg.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", "grey")
.attr("fill-opacity", .2)
.attr("stroke", "black")
.attr("stroke-width", 1.5)
.append("title")
// Do this to maintain access to the features you drew
.datum(function(d) { return d; })
.text(function(d) {
return d.properties.name;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="200"></svg>
更复杂的可以使用绝对定位div
,例如:
const data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"name": "Kitchen"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
0, 0
],
[
0, 11.4
],
[
7, 11.4
],
[
7, 0
],
[
0, 0
]
]
]
}
},
{
"type": "Feature",
"properties": {
"name": "Living room"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
7, 0
],
[
7, 11.4
],
[
12, 11.4
],
[
12, 0
],
[
7, 0
]
]
]
}
},
{
"type": "Feature",
"properties": {
"name": "Toilet"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
12, 0
],
[
12, 11.4
],
[
19, 11.4
],
[
19, 0
],
[
12, 0
]
]
]
}
}
]
};
var svg = d3.select("svg")
var width = +svg.attr("width")
var height = +svg.attr("height")
var tooltip = d3.select("#tooltip")
svg.attr("transform", "translate(" + width / 2 + ",0)")
var projection = d3.geoIdentity().fitSize([width, height], data)
var path = d3.geoPath(projection)
svg.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", "grey")
.attr("fill-opacity", .2)
.attr("stroke", "black")
.attr("stroke-width", 1.5)
.on("mousemove", function(d) {
// +3 as some offset to make sure spawning the tooltip doesn't
// accidentally also cause unhover and thus removing itself
tooltip
.html(d.properties.name)
.style("display", "block")
.style("left", d3.event.x + 3 + 'px')
.style("top", d3.event.y + 3 + 'px');
})
.on("mouseleave", function() {
tooltip
.style("display", null)
.style("left", null)
.style("top", null);
});
#tooltip {
position: absolute;
top: 0;
left: 0;
display: none;
border: solid 1px red;
padding: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="200"></svg>
<div id="tooltip"></div>