I have a moving <div> object. I want to show/update this tooltip info, let say every 2s. It works fine but the position doesn't change even if the object had moved, the tooltip keeps the initial position and stay static (sorry i didn't provide a working example).
How can I update its position to follow the <div> (not the mouse) ?
event.pageX and event.pageY
The description below is for event.pageX
Description: The mouse position relative to the left edge of the document.
Below is the code i had used in one of my application.
You can show the div below on a mouseover event.
date.selectAll("rect")
.data(function(d) {
return d.mattel_data;
})
.enter().append("rect")
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.y1);
})
.attr("height", function(d) {
return y(d.y0) - y(d.y1);
})
.style("fill", function(d) {
return color(d.name);
})
.on("mouseover", function(d) {
div.transition()
.duration(100)
.style("opacity", .9);
var hoverVal = (d.y1 - d.y0);
var formatter = new Intl.NumberFormat('en-US',{
style : 'currency',
currency : 'USD',
minimumFractionDigits : 2,
});
var pop = formatter.format(hoverVal);
// console.log(pop);
div.html("Value:" + pop + "<br/>" + d.name)
.style("left", (d3.event.pageX - 140) + "px")
.style("top", (d3.event.pageY - 80) + "px")
.style('position', 'absolute')
.style('font-size', '15px')
.style('background', function() {
return color(d.name);
})
.style('color', function() {
return getContrastYIQ(color(d.name));
})
})
.on("mouseout", function(d) {
div.transition()
.duration(200)
.style("opacity", 0);
});
See if that helps you out.
Also if you post your code here that will help to understand your problem more clearly
Related
'''
#Parent svg
svg.append('g')
.selectAll("dot")
.data(storage)
.join("circle")
.attr("cx", function (d) { return x(d.x); })
.attr("cy", function (d) { return y(d.y); })
.attr("r", .5)
.style("fill", "green")
.on("mouseover", function (e, d) {
d3.select(this).transition()
.duration(200)
div.style("left", (e.pageX) + "px")
.style("top", (e.pageY - 28) + "px");
console.log(e, d);
div.transition()
.duration(500)
.style("opacity", 0);
div.transition()
.duration(200)
.style("opacity", .9);
div.html(
'X, Y: ' + d.x + ", "+ d.y +
"<br>Pin: " + d.pinName +
"<br>Net: " + d.netName);
s_data = storage.filter(a => a.netName ===d.netName);
#Child svg
svg.append('g')
.selectAll("dot")
.data(s_data)
.join("circle")
.attr("cx", function (d) { return x(d.x); })
.attr("cy", function (d) { return y(d.y); })
.attr("r", .5)
.style("fill", "red")
})
.on('mouseout', function(d,i){
d3.select(this).transition()
.duration('200')
.style('fill', 'green');
})
'''
Initially all dots are green when I mouseover any one of the dots, the set of dots with common netName will highlight, after this I can't go back to normal, i,e I want all dots to be green again so that I can highlight other dots and check for there grouping. The data is basically a JSON object
Take a look at this example: https://codepen.io/ccasenove/pen/RwyzZrV
I have a unique id key on each dot and a netId attribute shared by some dots. If you specify a key function when you bind the data to a d3 selection, then you can obtain a sub selection of dots with the same netId like this:
const _data = data.filter(da => da.netId == d.netId);
svg.selectAll("circle")
.data(_data, d => d.id)
.style("fill", "red")
the d3 data function will return the update selection, i.e. dots that already exist with the ids in the filtered data. So you can change the color of this update selection in mouseover and mouseout functions.
I need to change the xy-position of an d3-foreignObject (textarea) after it is added to a group. When dragging it is simple, I do:
d3.select(this).attr("transform", "translate(" + (d.x = d3.event.x) + "," + (d.y = d3.event.y) + ")");
But how do I change the position manually? I tried setting .attr(x, 100), but nothing happens. Can please someone help me out.
The problem with your code (in the jsfiddle you linked) is that text is a selection for the <textarea> HTML element, not for the foreignObject. So, any change you do in the x attribute is actually applied to the <textarea>.
Solution: break your chain, making text just the selection for the foreignObject. Look at the demo below:
var svg = d3.select("body").append('svg')
.attr('width', 500)
.attr('height', 200)
.attr('style', 'outline: thin solid black;')
.style('background-color', '#f4f3f1');
var grp = svg.append("g")
.datum({
x: 0,
y: 0
})
.attr("class", "group");
var text = grp.append("foreignObject")
.datum({
x: 50,
y: 50,
width: 100,
height: 100
})
.attr("x", function(d) {
return d.x;
})
.attr('y', function(d) {
return d.y;
})
.attr('width', function(d) {
return d.width;
})
.attr('height', function(d) {
return d.height;
});
var textarea = text.append("xhtml:body")
.attr('xmlns', 'http://www.w3.org/1999/xhtml')
.append('textarea')
.attr("id", "text")
.style("width", 100 + "px")
.style("height", 100 + "px")
.property("value", "This foreign object doesn't stop!")
.style("text-align", "center");
move();
function move() {
text.transition()
.duration(1000)
.attr("x", 350)
.transition()
.duration(1000)
.attr("x", 50)
.each("end", move)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
I would like to ask if anyone know how to get the code to do similar chart like this https://www.theguardian.com/world/interactive/2013/feb/12/state-of-the-union-reading-level
It is written in D3 but I couldn't find similar codes online.
Thanks
I think this is just a fairly involved tooltip on a scatter plot. Here's a simpler example:
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// Add the scatterplot
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 5)
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); })
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div .html(formatTime(d.date) + "<br/>" + d.close)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
You might also find this other example useful.
I am trying to implement the FishEye lens (Cartesian) in my scatterplot.
I am trying to follow this approach, but apparently my selector already fails.
I have my FishEye defined as
var fisheye = d3.fisheye.circular().radius(120);
svg.on("mousemove", function() {
fisheye.focus(d3.mouse(this));
console.log("here " + points.selectAll("circle").length);
points.selectAll("circle").each(function(d) {
console.log("aaa");
d.fisheye = fisheye(d);
/*points.selectAll("circle")
.each(function(d) {
console.log("???");
this.attr("cx", function(d) { return d.fisheye.x; })
this.attr("cy", function(d) { return d.fisheye.y; })
this.attr("r", function(d) { console.log("hype"); return 10; });
}); */
});
});
and my points is defined as
points = svg.append("g")
.attr("class", "point")
.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) { // Set the x position using the x-scale
return x(d.x);
})
.attr("cy", function(d) { // Set the y position using the y-scale
return y(d.y);
})
.attr("r", 5) // Set the radius of every point to 5
.on("mouseover", function(d) { // On mouse over show and set the tooltip
if(!isBrushing){
tooltip.transition()
.duration(200)
.style("opacity", 0.9);
tooltip.html(d.symbol + "<br/> (" + parseFloat(x(d.x)).toFixed(4)
+ ", " + parseFloat(y(d.y)).toFixed(4) + ")")
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 28) + "px");
}
})
.on("mouseout", function(d) { // on mouseout, hide the tooltip.
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
The console.log with "here" is spamming when I am moving the mouse, and shows the correct amount. Hwoever, the each loop is never executed as I do not see "aaa". I have also tried to just use selectAll("circle") but that doesn't work either.
What am I doing wrong and how can I get my FishEye to work?
I have a bar chart and I have text values at the end of each bar. What I would like to do is set text to invisible, and on mouseover I'd like it to show the number associated with the bar, at the magnitude of that bar. I'm having trouble figuring out how to do this in an efficient manner.
var tooltip = d3.select("body").append("div")
.style("position", "absolute")
.attr("class", "tooltip")
.style("opacity", 0);
var rect = svg.selectAll("rect")
.attr("class", "rect")
.data(dataset)
.enter()
.append("rect")
.attr("y", function(d,i){
return yScale(i);
})
.attr("x", 0)
.attr("width", function(d,i){
return xScale(d);
})
.attr("height", h/dataset.length)
.style("fill", function(d,i){
return colors(d);
})
.on("mouseover", function(d){
d3.select(this).style("opacity", 0.5)
tooltip.transition()
.duration(200)
.style("opacity", 1);
tooltip.html(d)
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY + "px")
})
.on("mouseout", function(d){
d3.select(this).style("opacity", 1)
tooltip.transition()
.duration(500)
.style("opacity", 0)
});
Instead of mouseover and mouseout, I recommend doing it with $(this).hover and $(this).mousemove. Try something like this:
$(this).hover(
function() {
tooltip.transition()
.duration(200)
.style("opacity", 1)
// In order to trigger the magnitude or 'width' of the rect:
var rectWidth = $(this).attr("width");
}, function () {
tooltip.transition()
.duration(500)
.style("opacity", 1e-6)
}
);
/*$(this).mousemove(function(event) {
tooltip
.style("left", event.clientX + "px")
.style("top", event.clientY + "px")
});*/