我正在尝试在水平条形图上显示工具提示。如果我向下滚动页面,此工具提示将无法正常工作。
如果条形图在视图中并且不需要滚动,则此方法很好。但是,如果我在图表上方添加更多元素,则向下滚动时,工具提示会从鼠标指针移至更高位置。
请帮助我解决此问题。
代码如下:
//Ignore test data
var birthData = [{
"year": 1967,
"month": "January",
"births": 31502
},
{
"year": 1967,
"month": "February",
"births": 26703
},
{
"year": 1967,
"month": "March",
"births": 28853
},
{
"year": 1967,
"month": "April",
"births": 26958
},
{
"year": 1967,
"month": "May",
"births": 28591
},
{
"year": 1967,
"month": "June",
"births": 29545
},
{
"year": 1967,
"month": "July",
"births": 30086
},
{
"year": 1967,
"month": "August",
"births": 30947
},
{
"year": 1967,
"month": "September",
"births": 32338
},
{
"year": 1967,
"month": "October",
"births": 32296
},
{
"year": 1967,
"month": "November",
"births": 30326
},
{
"year": 1967,
"month": "December",
"births": 28994
}
]
//d3 code
var minYear = d3.min(birthData, function(d) {
return d.year;
});
var maxYear = d3.max(birthData, function(d) {
return d.year;
});
var width = 600;
var height = 600;
var barPadding = 30;
var numBars = 12;
var barWidth = 10;
var maxBirths = d3.max(birthData, function(d) {
return d.births;
});
var xScale = d3.scaleLinear()
.domain([0, maxBirths])
.range([0, width]);
var tooltip = d3.select('body').append('div').classed('tooltip', true);
var g = d3.select('svg')
.attr('width', width)
.attr('height', height)
.selectAll('g')
.data(birthData.filter(function(d) {
return d.year === minYear;
}))
.enter()
.append('g')
.attr('transform', 'translate(40, 40)');
g.append('rect')
.attr('width', function(d) {
return xScale(maxBirths);
})
.attr('height', barWidth)
.attr('x', 0)
.attr('y', function(d, i) {
return (barWidth + barPadding) * i;
}).attr('fill', 'grey');
g.append('rect')
.attr('width', function(d) {
return xScale(d.births);
})
.attr('height', barWidth)
.attr('x', 0)
.attr('y', function(d, i) {
return (barWidth + barPadding) * i;
}).attr('fill', 'blue')
.classed('original', true);
g.append('text')
.attr('x', 0)
.attr('y', function(d, i) {
return (barWidth + barPadding) * i;
})
.text(function(d) {
return d.month;
});
g.on('mousemove', showToolTip)
.on('mouseout', hideToolTip)
.on('touchstart', showToolTip)
.on('touchend', hideToolTip);
function hideToolTip() {
tooltip
.style('opacity', 0);
}
function showToolTip(d) {
tooltip
.style('opacity', 1)
.style('left', d3.event.x + 'px')
.style('top', d3.event.y + 'px')
.text(d.month + ': ' + d.births)
};
svg,
input {
margin: 0 auto 10px;
display: block;
}
.tooltip {
opacity: 0;
position: absolute;
pointer-events: none;
background-color: lightblue;
border: 8px solid blue;
border-radius: 8px;
padding: 15px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D3 Birth Chart</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div style="height: 200px; width: 200px">
<h2>Dashboard</h2>
</div>
<svg>
</svg>
<script src="https://d3js.org/d3.v5.js"></script>
</body>
</html>
答案 0 :(得分:0)
使用d3.event.x
和d3.event.y
代替d3.event.pageX
和d3.event.pageY
。 event.pageX:
返回相对于整个文档的左边缘单击鼠标的X(水平)坐标(以像素为单位)。这包括文档中当前不可见的任何部分。
pageY
也是如此。
这是您所做的更改的代码:
//Ignore test data
var birthData = [{
"year": 1967,
"month": "January",
"births": 31502
},
{
"year": 1967,
"month": "February",
"births": 26703
},
{
"year": 1967,
"month": "March",
"births": 28853
},
{
"year": 1967,
"month": "April",
"births": 26958
},
{
"year": 1967,
"month": "May",
"births": 28591
},
{
"year": 1967,
"month": "June",
"births": 29545
},
{
"year": 1967,
"month": "July",
"births": 30086
},
{
"year": 1967,
"month": "August",
"births": 30947
},
{
"year": 1967,
"month": "September",
"births": 32338
},
{
"year": 1967,
"month": "October",
"births": 32296
},
{
"year": 1967,
"month": "November",
"births": 30326
},
{
"year": 1967,
"month": "December",
"births": 28994
}
]
//d3 code
var minYear = d3.min(birthData, function(d) {
return d.year;
});
var maxYear = d3.max(birthData, function(d) {
return d.year;
});
var width = 600;
var height = 600;
var barPadding = 30;
var numBars = 12;
var barWidth = 10;
var maxBirths = d3.max(birthData, function(d) {
return d.births;
});
var xScale = d3.scaleLinear()
.domain([0, maxBirths])
.range([0, width]);
var tooltip = d3.select('body').append('div').classed('tooltip', true);
var g = d3.select('svg')
.attr('width', width)
.attr('height', height)
.selectAll('g')
.data(birthData.filter(function(d) {
return d.year === minYear;
}))
.enter()
.append('g')
.attr('transform', 'translate(40, 40)');
g.append('rect')
.attr('width', function(d) {
return xScale(maxBirths);
})
.attr('height', barWidth)
.attr('x', 0)
.attr('y', function(d, i) {
return (barWidth + barPadding) * i;
}).attr('fill', 'grey');
g.append('rect')
.attr('width', function(d) {
return xScale(d.births);
})
.attr('height', barWidth)
.attr('x', 0)
.attr('y', function(d, i) {
return (barWidth + barPadding) * i;
}).attr('fill', 'blue')
.classed('original', true);
g.append('text')
.attr('x', 0)
.attr('y', function(d, i) {
return (barWidth + barPadding) * i;
})
.text(function(d) {
return d.month;
});
g.on('mousemove', showToolTip)
.on('mouseout', hideToolTip)
.on('touchstart', showToolTip)
.on('touchend', hideToolTip);
function hideToolTip() {
tooltip
.style('opacity', 0);
}
function showToolTip(d) {
tooltip
.style('opacity', 1)
.style('left', d3.event.pageX + 'px')
.style('top', d3.event.pageY + 'px')
.text(d.month + ': ' + d.births)
};
svg,
input {
margin: 0 auto 10px;
display: block;
}
.tooltip {
opacity: 0;
position: absolute;
pointer-events: none;
background-color: lightblue;
border: 8px solid blue;
border-radius: 8px;
padding: 15px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D3 Birth Chart</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div style="height: 200px; width: 200px">
<h2>Dashboard</h2>
</div>
<svg>
</svg>
<script src="https://d3js.org/d3.v5.js"></script>
</body>
</html>