Reputation: 145
I'm been trying to display two charts in my web page using the d3 v4 plugin
I have been following some examples about tooltip's usage but I have a problem: In the first chart the tooltips are displayed in the correct position (above the bars) but in the bottom chart, the tooltips seems to going to the bottom of the page.
This is a very simple example: https://jsfiddle.net/xvs98vru/
HTML
<div class="container">
<div class="row">
<div class="col-md-12">
<div id="chart1" class="c"></div>
</div>
<div class="col-md-12">
<div id="chart2" class="c"></div>
</div>
</div>
</div>
CSS
body { padding: 20px; }
.c {
height: 300px;
width: 400px;
margin-bottom: 10px;
}
.tooltipx {
pointer-events: none;
position: absolute;
display: none;
min-width: 50px;
height: auto;
background: none repeat scroll 0 0 #ffffff;
padding: 4px 10px 4px 10px;
border-radius: 4px;
text-align: left;
line-height: 1.3;
color: #5B6770;
box-shadow: 0px 3px 9px rgba(0, 0, 0, .15);
}
JS
(function() {
var mrg = { t:10, r:20, b:30, l:20 };
var data = [
{ id: 1, amount: 6 },
{ id: 2, amount: 5 },
{ id: 3, amount: 2 },
{ id: 4, amount: 8 }
];
function loadChart(container) {
var width = 400 - mrg.l - mrg.r;
var height = 300 - mrg.t - mrg.b;
var color = d3.scaleOrdinal(d3.schemeCategory10);
var tooltip = d3.select(container).append("div")
.attr("class", "tooltipx")
.style("opacity", 0);
var x = d3.scaleBand().range([0, width]).padding(0.1);
var y = d3.scaleLinear().range([height, 0]);
x.domain([1, 2, 3, 4]);
y.domain([0, 10]);
var svg = d3.select(container).append("svg")
.attr("width", width + mrg.l + mrg.r)
.attr("height", height + mrg.t + mrg.b)
.append("g")
.attr("transform", "translate(" + mrg.l + "," + mrg.t + ")");
svg.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function(n) { return x(n.id); })
.attr("y", function(n) { return y(n.amount); })
.attr("width", x.bandwidth())
.attr("height", function(n) { return height - y(n.amount); })
.attr("fill", function(n, i) { return color(i); })
.on("mousemove", function(n) {
tooltip
.style("opacity", 1)
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY + "px")
.style("display", "inline-block")
.html("<span>Hola</span>")
})
.on("mouseout", function(n) { tooltip.style("opacity", 0); });
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
svg.append("g").call(d3.axisLeft(y));
}
function init() {
loadChart("#chart1");
loadChart("#chart2");
}
init();
}());
Thank's for the support
Regards
Upvotes: 2
Views: 3113
Reputation: 102174
Since you're using pageX
and pageY
for positioning the tooltips, don't append them to each selected div... instead of that, append them to the <body>
:
var tooltip = d3.select("body").append("div")
Here is your code with that change only:
(function() {
var mrg = {
t: 10,
r: 20,
b: 30,
l: 20
};
var data = [{
id: 1,
amount: 6
},
{
id: 2,
amount: 5
},
{
id: 3,
amount: 2
},
{
id: 4,
amount: 8
}
];
function loadChart(container) {
var width = 400 - mrg.l - mrg.r;
var height = 300 - mrg.t - mrg.b;
var color = d3.scaleOrdinal(d3.schemeCategory10);
var tooltip = d3.select("body").append("div")
.attr("class", "tooltipx")
.style("opacity", 0);
var x = d3.scaleBand().range([0, width]).padding(0.1);
var y = d3.scaleLinear().range([height, 0]);
x.domain([1, 2, 3, 4]);
y.domain([0, 10]);
var svg = d3.select(container).append("svg")
.attr("width", width + mrg.l + mrg.r)
.attr("height", height + mrg.t + mrg.b)
.append("g")
.attr("transform", "translate(" + mrg.l + "," + mrg.t + ")");
svg.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function(n) {
return x(n.id);
})
.attr("y", function(n) {
return y(n.amount);
})
.attr("width", x.bandwidth())
.attr("height", function(n) {
return height - y(n.amount);
})
.attr("fill", function(n, i) {
return color(i);
})
.on("mousemove", function(n) {
tooltip
.style("opacity", 1)
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY + "px")
.style("display", "inline-block")
.html("<span>Hola</span>")
})
.on("mouseout", function(n) {
tooltip.style("opacity", 0);
});
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
svg.append("g").call(d3.axisLeft(y));
}
function init() {
loadChart("#chart1");
loadChart("#chart2");
}
init();
}());
body {
padding: 20px;
}
.c {
height: 300px;
width: 400px;
margin-bottom: 10px;
}
.tooltipx {
pointer-events: none;
position: absolute;
display: none;
min-width: 50px;
height: auto;
background: none repeat scroll 0 0 #ffffff;
padding: 4px 10px 4px 10px;
border-radius: 4px;
text-align: left;
line-height: 1.3;
color: #5B6770;
box-shadow: 0px 3px 9px rgba(0, 0, 0, .15);
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<div class="container">
<div class="row">
<div class="col-md-12">
<div id="chart1" class="c"></div>
</div>
<div class="col-md-12">
<div id="chart2" class="c"></div>
</div>
</div>
</div>
Upvotes: 4