我正在D3.js中构建一个Choropleth地图。
为了使用户更容易理解信息,我决定添加HTML工具提示。
为此,我定义了一个名为tooptip的变量:
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip");
当我绑定数据时,我添加了:
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html("<strong>" + d.properties.average_price_per_pound + "</strong>" + "<br/>" + "Population: " +
(d.properties.average_price_per_pound).toLocaleString() + " Million")
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
})
但是它不能正常工作,就像下面的图像所示(注意:当我将鼠标悬停在某个状态上时,红色显示)。
我尝试了一种不同的方法,并且通过添加一个简单的文本工具提示(在我尝试添加html工具提示的位置),即使我的目标是添加html工具提示,我也能够使它工作:
.text(d => d.properties.average_price_per_pound);
考虑到我打算添加HTML工具提示,在此过程中提供的任何帮助都将受到赞赏。
我可能会在我的 app.js 处留下波纹,
app.js
// Define width and height
var chart_width = 800;
var chart_height = 600;
// Define the color scale
var color = d3.scaleQuantize().range([
"#f7fbff",
"#deebf7",
"#c6dbef",
"#9ecae1",
"#6baed6",
"#4292c6",
"#2171b5",
"#08519c",
"#08306b"
]);
// Navbar
function openNav() {
document.getElementById("mySidenav").style.width = "100%";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
}
// Define the Tooltip
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip");
// Define the Map Projection
var projection = d3.geoAlbersUsa()
.translate([ 0,0 ]);
var path = d3.geoPath( projection );
// Create SVG
var svg = d3.select("#chart")
.append("svg")
.attr("width", chart_width)
.attr("height", chart_height);
// Zoom
var zoom_map = d3.zoom()
.scaleExtent([ 0.5, 3.0 ])
.translateExtent([
[ -1000, -500 ],
[ 1000, 500 ]
])
.on( 'zoom', function(){
// console.log( d3.event );
var offset = [
d3.event.transform.x,
d3.event.transform.y
];
var scale = d3.event.transform.k * 1100;
projection.translate( offset )
.scale( scale );
svg.selectAll( 'path' )
.transition()
.attr( 'd', path );
svg.selectAll( 'circle' )
.transition()
.attr( "cx", function(d) {
return projection([d.longitude, d.latitude])[0];
})
.attr( "cy", function(d) {
return projection([d.longitude, d.latitude])[1];
});
});
var map = svg.append( 'g' )
.attr( 'id', 'map' )
.call( zoom_map )
.call(
zoom_map.transform,
d3.zoomIdentity
.translate( chart_width / 2, chart_height / 2 )
.scale( 1 )
);
map.append( 'rect' )
.attr( 'x', 0 )
.attr( 'y', 0 )
.attr( 'class', "mapsvg")
.attr( 'width', chart_width )
.attr( 'height', chart_height )
.attr( 'opacity', 0 );
// Load Data
var honeyyear = document.getElementById("vardatayear").value || 2013;
// if(!honeyyear){
// honeyyear = 2013
// }
// Select what are we analyzing
// var honeyattribute = document.getElementById('some_input_id').value;
d3.json( `data/HoneyProduction-${honeyyear}.json`, function( honey_data ){
color.domain([
d3.min( honey_data, function(d){
return d.average_price_per_pound;
}),
d3.max( honey_data, function(d){
return d.average_price_per_pound;
})
]);
// Load GeoJson Data
d3.json( 'data/us.json', function( us_data ){
us_data.features.forEach(function(us_e, us_i){
honey_data.forEach(function(h_e,h_i){
if( us_e.properties.name !== h_e.state ){
return null;
}
us_data.features[us_i].properties.average_price_per_pound = parseFloat(h_e.average_price_per_pound);
});
});
// Bind Data
map.selectAll( 'path' )
.data( us_data.features )
.enter()
.append( 'path' )
.attr( 'd', path )
.attr( 'fill', function( d ){
var average_price_per_pound = d.properties.average_price_per_pound;
return average_price_per_pound ? color( average_price_per_pound ) : '#525252';
})
.attr( 'stroke', '#fff' )
.attr( 'stroke-width', 1 )
.append('title')
// .text(d => console.log(d))
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html("<strong>" + d.properties.average_price_per_pound + "</strong>" + "<br/>" + "Population: " +
(d.properties.average_price_per_pound).toLocaleString() + " Million")
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
})
// // For the simple tooltip
// .text(d => d.properties.average_price_per_pound);
});
// Legend
const x = d3.scaleLinear()
.domain(d3.extent(color.domain()))
.rangeRound([500, 750]);
const g = svg.append("g")
.attr( "class", "legend" )
.attr("transform", "translate(0,40)");
g.selectAll("rect")
.data(color.range().map(d => color.invertExtent(d)))
.enter().append("rect")
.attr("height", 8)
.attr("x", d => x(d[0]))
.attr("width", d => x(d[1]) - x(d[0]))
.attr("fill", d => color(d[0]));
g.append("text")
.attr("class", "caption")
.attr("x", x.range()[0])
.attr("y", -6)
.attr("fill", "#fff")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text('Average Price per Pound (cents)');
g.call(d3.axisBottom(x)
.tickSize(13)
.tickFormat(( honey_data, function(d){
return d.average_price_per_pound;
}),)
.tickValues(color.range().slice(1).map(d => color.invertExtent(d)[0])))
.select(".domain")
.remove();
// svg.append("g")
// .selectAll("path")
// .data(honey_data, function(d){
// return d.average_price_per_pound;
// })
// .enter().append("path")
// .attr("fill", d => color(d.average_price_per_pound))
// .attr("d", path)
// .append("title")
// .text(d => (d.average_price_per_pound));
//
// svg.append("path")
// .datum(honey_data, function(d){
// return d.average_price_per_pound;
// })
// .attr("fill", "none")
// .attr("stroke", "white")
// .attr("stroke-linejoin", "round")
// .attr("d", path);
});
// Panning
d3.selectAll( '#buttons button.panning' ).on( 'click', function(){
var x = 0;
var y = 0;
var distance = 100;
var direction = d3.select( this ).attr( 'class' ).replace( 'panning ', '' );
if( direction === "up" ){
y += distance; // Increase y offset
}else if( direction === "down" ){
y -= distance; // Decrease y offset
}else if( direction === "left" ){
x += distance; // Increase x offset
}else if( direction === "right" ){
x -= distance; // Decrease x offset
}
map.transition()
.call( zoom_map.translateBy, x, y );
});
// Zooming
d3.selectAll( '#buttons button.zooming' ).on( 'click', function(){
var scale = 1;
var direction = d3.select(this).attr("class").replace( 'zooming ', '' );
if( direction === "in" ){
scale = 1.25;
}else if(direction === "out"){
scale = 0.75;
}
map.transition()
.call(zoom_map.scaleBy, scale);
});
// Slider
function update(year){
slider.property("value", year);
d3.select(".year").text(year);
// honeyyear.style("fill", function(d) {
// return color(d.properties.years[year][0].rate)
};
var slider = d3.select(".slider")
.append("input")
.attr("type", "range")
.attr("min", 2009)
.attr("max", 2013)
.attr("step", 1)
.on("input", function() {
var year = this.value;
update(year);
});
update(2013);
答案 0 :(得分:1)
问题在于,append('title')
丢失了对路径的选择,因此,您基本上是将一个鼠标悬停事件监听器添加到一个空的svg <title>
标记中,该标记是该路径的子代实际想将事件处理程序附加到此。
只要在附加事件处理程序后 ,您仍可以在该链中附加标题。
请参阅以下这些并行示例:
这有效-事件处理程序已附加到所需元素
var tooltip = d3
.select("body")
.append("div")
.attr("class", "tooltip");
const sampleData = [
{
properties: {
average_price_per_pound: 5000
}
},
{
properties: {
average_price_per_pound: 15000
}
},
{
properties: {
average_price_per_pound: 555000
}
}
];
d3
.select("body")
.selectAll(".item")
.data(sampleData)
.enter()
.append("div")
.classed("item", true)
.html(d => {
return d.properties.average_price_per_pound;
})
.on("mouseover", function(d) {
tooltip.html(
`<strong>${
d.properties.average_price_per_pound
}</strong><br/>Population: ${d.properties.average_price_per_pound.toLocaleString()} Million`
);
});
.tooltip {
position: absolute;
background: white;
border: 2px solid black;
left: 100px;
padding: 5px;
border-radius: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
不起作用-事件处理程序已附加到不需要的空子元素上
var tooltip = d3
.select("body")
.append("div")
.attr("class", "tooltip");
const sampleData = [
{
properties: {
average_price_per_pound: 5000
}
},
{
properties: {
average_price_per_pound: 15000
}
},
{
properties: {
average_price_per_pound: 555000
}
}
];
d3
.select("body")
.selectAll(".item")
.data(sampleData)
.enter()
.append("div")
.classed("item", true)
.html(d => {
return d.properties.average_price_per_pound;
})
.append('span')
.on("mouseover", function(d) {
tooltip.html(
`<strong>${
d.properties.average_price_per_pound
}</strong><br/>Population: ${d.properties.average_price_per_pound.toLocaleString()} Million`
);
});
.tooltip {
position: absolute;
background: white;
border: 2px solid black;
left: 100px;
padding: 5px;
border-radius: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>