D3js:如何让我的工具提示出现在选择的旁边?
D3js: How do I make my tooltip appear next to the selection?
我正在尝试为我的热图可视化上的每个方块提供工具提示。但是,我无法将它正确定位在光标旁边。这是发生了什么:
我的代码是这样的:
const margin = {
top: 20,
right: 20,
bottom: 30,
left: 150,
};
const width = 960 - margin.left - margin.right;
const height = 2500 - margin.top - margin.bottom;
let chart = d3
.select("#chart2")
.append("div")
// Set id to chartArea
.attr("id", "chartArea")
.classed("chart", true)
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Make sure to create a separate SVG for the XAxis
let axis = d3
.select("#chart2")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", 40)
.append("g")
.attr("transform", "translate(" + margin.left + ", 0)");
// Load the data
d3.csv("https://raw.githubusercontent.com/thedivtagguy/files/main/land_use.csv").then(function(data) {
// console.log(data);
const years = Array.from(new Set(data.map((d) => d.year)));
const countries = Array.from(new Set(data.map((d) => d.entity)));
countries.reverse();
const x = d3.scaleBand().range([0, width]).domain(years).padding(0.01);
// create a tooltip
var tooltip = d3
// Select all boxes in the chart
.select("#chart2")
.append("div")
.classed("tooltip", true)
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
const mouseover = function(event, d) {
tooltip.style("opacity", 1);
d3.select(this).style("stroke", "black").style("opacity", 1);
};
const mousemove = function(event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
// Position the tooltip next to the cursor
.style("left", event.x + "px")
.style("top", event.y / 2 + "px");
};
const mouseleave = function(event, d) {
tooltip.style("opacity", 0);
d3.select(this).style("stroke", "none").style("opacity", 0.8);
};
const y = d3.scaleBand().range([height, 0]).domain(countries).padding(0.01);
// Only 10 years
axis
.call(d3.axisBottom(x).tickValues(years.filter((d, i) => !(i % 10))))
.selectAll("text")
.style("color", "black")
.style("position", "fixed")
.attr("transform", "translate(-10,10)rotate(-45)")
.style("text-anchor", "end");
chart
.append("g")
.call(d3.axisLeft(y))
.selectAll("text")
.style("color", "black")
.attr("transform", "translate(-10,0)")
.style("text-anchor", "end");
const colorScale = d3
.scaleSequential()
.domain([0, d3.max(data, (d) => d.change)])
.interpolator(d3.interpolateInferno);
// add the squares
chart
.selectAll()
.data(data, function(d) {
return d.year + ":" + d.entity;
})
.join("rect")
// Add id-s
.attr("id", function(d) {
return d.year + ":" + d.entity;
})
.attr("x", function(d) {
return x(d.year);
})
.attr("y", function(d) {
return y(d.entity);
})
.attr("width", x.bandwidth())
.attr("height", y.bandwidth())
.style("fill", function(d) {
return colorScale(d.change);
console.log(d.change);
})
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave);
});
#chart2 .chart {
width: 960px;
max-height: 900px;
overflow-y: scroll;
overflow-x: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<div id="chart2" class="mx-auto"></div>
我想我知道为什么会这样。因为我像这样将 tooltip
iv 附加到 chart2
div,所以所有定位都是相对于 div 发生的,这意味着它不可避免地会位于整个图表下方,并且不在上面:
// create a tooltip
var tooltip = d3
// Select all boxes in the chart
.select("#chart2")
.append("div")
.classed("tooltip", true)
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
const mousemove = function(event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
// Position the tooltip next to the cursor
.style("left", event.x + "px")
.style("top", event.y / 2 + "px");
};
但是我还能怎么做呢?我尝试通过悬停在 rect
元素上的 select 尝试,但没有奏效。我正在尝试做类似 this.
的事情
我该如何解决这个问题?
只需在 mousemove
函数中添加 .style("position","absolute");
并将顶部样式更改为 .style("top", event.y + "px")
const margin = {
top: 20,
right: 20,
bottom: 30,
left: 150,
};
const width = 960 - margin.left - margin.right;
const height = 2500 - margin.top - margin.bottom;
let chart = d3
.select("#chart2")
.append("div")
// Set id to chartArea
.attr("id", "chartArea")
.classed("chart", true)
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Make sure to create a separate SVG for the XAxis
let axis = d3
.select("#chart2")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", 40)
.append("g")
.attr("transform", "translate(" + margin.left + ", 0)");
// Load the data
d3.csv("https://raw.githubusercontent.com/thedivtagguy/files/main/land_use.csv").then(function(data) {
// console.log(data);
const years = Array.from(new Set(data.map((d) => d.year)));
const countries = Array.from(new Set(data.map((d) => d.entity)));
countries.reverse();
const x = d3.scaleBand().range([0, width]).domain(years).padding(0.01);
// create a tooltip
var tooltip = d3
// Select all boxes in the chart
.select("#chart2")
.append("div")
.classed("tooltip", true)
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
const mouseover = function(event, d) {
tooltip.style("opacity", 1);
d3.select(this).style("stroke", "black").style("opacity", 1);
};
const mousemove = function(event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
// Position the tooltip next to the cursor
.style("left", event.x + "px")
.style("top", event.y + "px")
.style("position","absolute");
};
const mouseleave = function(event, d) {
tooltip.style("opacity", 0);
d3.select(this).style("stroke", "none").style("opacity", 0.8);
};
const y = d3.scaleBand().range([height, 0]).domain(countries).padding(0.01);
// Only 10 years
axis
.call(d3.axisBottom(x).tickValues(years.filter((d, i) => !(i % 10))))
.selectAll("text")
.style("color", "black")
.style("position", "fixed")
.attr("transform", "translate(-10,10)rotate(-45)")
.style("text-anchor", "end");
chart
.append("g")
.call(d3.axisLeft(y))
.selectAll("text")
.style("color", "black")
.attr("transform", "translate(-10,0)")
.style("text-anchor", "end");
const colorScale = d3
.scaleSequential()
.domain([0, d3.max(data, (d) => d.change)])
.interpolator(d3.interpolateInferno);
// add the squares
chart
.selectAll()
.data(data, function(d) {
return d.year + ":" + d.entity;
})
.join("rect")
// Add id-s
.attr("id", function(d) {
return d.year + ":" + d.entity;
})
.attr("x", function(d) {
return x(d.year);
})
.attr("y", function(d) {
return y(d.entity);
})
.attr("width", x.bandwidth())
.attr("height", y.bandwidth())
.style("fill", function(d) {
return colorScale(d.change);
console.log(d.change);
})
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave);
});
#chart2 .chart {
width: 960px;
max-height: 900px;
overflow-y: scroll;
overflow-x: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<div id="chart2" class="mx-auto"></div>
我正在尝试为我的热图可视化上的每个方块提供工具提示。但是,我无法将它正确定位在光标旁边。这是发生了什么:
我的代码是这样的:
const margin = {
top: 20,
right: 20,
bottom: 30,
left: 150,
};
const width = 960 - margin.left - margin.right;
const height = 2500 - margin.top - margin.bottom;
let chart = d3
.select("#chart2")
.append("div")
// Set id to chartArea
.attr("id", "chartArea")
.classed("chart", true)
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Make sure to create a separate SVG for the XAxis
let axis = d3
.select("#chart2")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", 40)
.append("g")
.attr("transform", "translate(" + margin.left + ", 0)");
// Load the data
d3.csv("https://raw.githubusercontent.com/thedivtagguy/files/main/land_use.csv").then(function(data) {
// console.log(data);
const years = Array.from(new Set(data.map((d) => d.year)));
const countries = Array.from(new Set(data.map((d) => d.entity)));
countries.reverse();
const x = d3.scaleBand().range([0, width]).domain(years).padding(0.01);
// create a tooltip
var tooltip = d3
// Select all boxes in the chart
.select("#chart2")
.append("div")
.classed("tooltip", true)
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
const mouseover = function(event, d) {
tooltip.style("opacity", 1);
d3.select(this).style("stroke", "black").style("opacity", 1);
};
const mousemove = function(event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
// Position the tooltip next to the cursor
.style("left", event.x + "px")
.style("top", event.y / 2 + "px");
};
const mouseleave = function(event, d) {
tooltip.style("opacity", 0);
d3.select(this).style("stroke", "none").style("opacity", 0.8);
};
const y = d3.scaleBand().range([height, 0]).domain(countries).padding(0.01);
// Only 10 years
axis
.call(d3.axisBottom(x).tickValues(years.filter((d, i) => !(i % 10))))
.selectAll("text")
.style("color", "black")
.style("position", "fixed")
.attr("transform", "translate(-10,10)rotate(-45)")
.style("text-anchor", "end");
chart
.append("g")
.call(d3.axisLeft(y))
.selectAll("text")
.style("color", "black")
.attr("transform", "translate(-10,0)")
.style("text-anchor", "end");
const colorScale = d3
.scaleSequential()
.domain([0, d3.max(data, (d) => d.change)])
.interpolator(d3.interpolateInferno);
// add the squares
chart
.selectAll()
.data(data, function(d) {
return d.year + ":" + d.entity;
})
.join("rect")
// Add id-s
.attr("id", function(d) {
return d.year + ":" + d.entity;
})
.attr("x", function(d) {
return x(d.year);
})
.attr("y", function(d) {
return y(d.entity);
})
.attr("width", x.bandwidth())
.attr("height", y.bandwidth())
.style("fill", function(d) {
return colorScale(d.change);
console.log(d.change);
})
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave);
});
#chart2 .chart {
width: 960px;
max-height: 900px;
overflow-y: scroll;
overflow-x: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<div id="chart2" class="mx-auto"></div>
我想我知道为什么会这样。因为我像这样将 tooltip
iv 附加到 chart2
div,所以所有定位都是相对于 div 发生的,这意味着它不可避免地会位于整个图表下方,并且不在上面:
// create a tooltip
var tooltip = d3
// Select all boxes in the chart
.select("#chart2")
.append("div")
.classed("tooltip", true)
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
const mousemove = function(event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
// Position the tooltip next to the cursor
.style("left", event.x + "px")
.style("top", event.y / 2 + "px");
};
但是我还能怎么做呢?我尝试通过悬停在 rect
元素上的 select 尝试,但没有奏效。我正在尝试做类似 this.
我该如何解决这个问题?
只需在 mousemove
函数中添加 .style("position","absolute");
并将顶部样式更改为 .style("top", event.y + "px")
const margin = {
top: 20,
right: 20,
bottom: 30,
left: 150,
};
const width = 960 - margin.left - margin.right;
const height = 2500 - margin.top - margin.bottom;
let chart = d3
.select("#chart2")
.append("div")
// Set id to chartArea
.attr("id", "chartArea")
.classed("chart", true)
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Make sure to create a separate SVG for the XAxis
let axis = d3
.select("#chart2")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", 40)
.append("g")
.attr("transform", "translate(" + margin.left + ", 0)");
// Load the data
d3.csv("https://raw.githubusercontent.com/thedivtagguy/files/main/land_use.csv").then(function(data) {
// console.log(data);
const years = Array.from(new Set(data.map((d) => d.year)));
const countries = Array.from(new Set(data.map((d) => d.entity)));
countries.reverse();
const x = d3.scaleBand().range([0, width]).domain(years).padding(0.01);
// create a tooltip
var tooltip = d3
// Select all boxes in the chart
.select("#chart2")
.append("div")
.classed("tooltip", true)
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
const mouseover = function(event, d) {
tooltip.style("opacity", 1);
d3.select(this).style("stroke", "black").style("opacity", 1);
};
const mousemove = function(event, d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
// Position the tooltip next to the cursor
.style("left", event.x + "px")
.style("top", event.y + "px")
.style("position","absolute");
};
const mouseleave = function(event, d) {
tooltip.style("opacity", 0);
d3.select(this).style("stroke", "none").style("opacity", 0.8);
};
const y = d3.scaleBand().range([height, 0]).domain(countries).padding(0.01);
// Only 10 years
axis
.call(d3.axisBottom(x).tickValues(years.filter((d, i) => !(i % 10))))
.selectAll("text")
.style("color", "black")
.style("position", "fixed")
.attr("transform", "translate(-10,10)rotate(-45)")
.style("text-anchor", "end");
chart
.append("g")
.call(d3.axisLeft(y))
.selectAll("text")
.style("color", "black")
.attr("transform", "translate(-10,0)")
.style("text-anchor", "end");
const colorScale = d3
.scaleSequential()
.domain([0, d3.max(data, (d) => d.change)])
.interpolator(d3.interpolateInferno);
// add the squares
chart
.selectAll()
.data(data, function(d) {
return d.year + ":" + d.entity;
})
.join("rect")
// Add id-s
.attr("id", function(d) {
return d.year + ":" + d.entity;
})
.attr("x", function(d) {
return x(d.year);
})
.attr("y", function(d) {
return y(d.entity);
})
.attr("width", x.bandwidth())
.attr("height", y.bandwidth())
.style("fill", function(d) {
return colorScale(d.change);
console.log(d.change);
})
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave);
});
#chart2 .chart {
width: 960px;
max-height: 900px;
overflow-y: scroll;
overflow-x: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<div id="chart2" class="mx-auto"></div>