I have a bar chart that I want to be able to hover over the bars and display some data on the top of the chart as text.
I don't want to use tooltips and when I change my text to a normal string like "boom" it will display that on mouse entry. However, it wont display the data.
I have the mouseenter and the function it calls in the code below. Basically I need a way for the mousenter to tell the function what the data it. For some reason it wont do that.
Ive tried useing .text(d3.select(this).text(d.data)) in the function.
I have also tried getting rid of the function and having it all as one code. Also did not work
.on("mouseenter", flash("mode0Danceability"))
function flash(name) {
return function() {
svg.append("text").attr({id: "fish"})
.attr("class", "boom")
.attr("x", 45)
.attr("y", -33)
.text(svg.html(d.mode0Danceability))
.style("font", "20px sans-serif")
.style("fill", "steelblue");
};
}
Best method IS to create a tooltip, just give it no borders and append it as a text to a particular location not as a div.
Related
So, I am thinking something along the lines of a tool tip or a pop-up, except with much more information in it, and I also want every information box to be in the same location on the page. Overall, I just want to be about to click on an SVG (that represents some data element), and on a click event, trigger and information box to pop up in front of it; maybe even give it it's own close function if it covers the SVG. I know I have seen this many times before, but the exact name is escaping me at the moment.
Right now, I have a circle:
node.append("circle")
.attr("cx", sankey.nodeWidth()/2)
.attr("cy", function(d){return d.dy/2;})
.attr("r",function(d){return Math.sqrt(d.dy);})
.style("fill", function(d){return d.color = color(d.name.replace(/ .*/,""));})
.style("stroke", function(d){return d3.rgb(d.color).darker(1);})
.style("stroke-width",5)
.on("mouseover", tip.show)
.on("mouseout", tip.hide)
.on("click", changeColor(function(d){return d.color;}))
.append("title")
I'm hoping to write something like:
.on("click",function(d){/*Create a rect element*/})
.append("text", "This element represents the "+d.name+" element and will weigh approximately "+d.weight+"lbs.")
.attr("cx", 50)
.attr("cy", 50)
.on("click_exit?" function(d){this.remove();})
I am not certain how to approach this, but I just want a text box to display on click and have an exit button (or some closing method) to close it. Can I add something like the above code to my previous code, or must I create an entire new svg element completely disjoint from it?
I've done things similar to this before, i've found that SVG can be a real pain when not doing actual d3 graphical stuff. I would work with html in this case.
What i did was create an html element with the desired template, absolutely position it where i wanted, and then set display:none or opacity:0.
Then for your onClick function
.on("click",function(d){
d3.select('.my-info-box p')
.append(d)
.style('display','block')
})
This is the bare bones functionality. The takeaway here is to use html and not svg. To close it you can position a × in the top right/left of the box, and then onClick, close the info box.
I created two different SVGs. One contains a graph with data points, the other one contains three lines. The lines color are supposed to be dependent on the selected data point and I have not managed to get this done yet (more details below). The jsfiddle can be found here: jsfiddle.
What I would like to do is to change the color of the three lines when I mouseover the data points. I managed to change the color of all lines to the same color but would actually like to use the color that is associated to the respective data point but I don't know how I can pass the color data which are stored in myColors to the function where I set the lines' color.
The relevant code is shown below. I add a graph with datapoints to mySvg and when I mouseover the data points, I change their color to black and the color of the lines in the other SVG to green. However, instead of changing all lines' color to green, I would actually like to change their colors to the colors defined in myColors (see the above linked jsfiddle to find the data). How could I do this?
var circles = mySvg.selectAll("circle")
.data(lineData)
.enter()
.append("circle");
var circleAttributes = circles
.attr("cx", function (d) { return xScale(d.x); })
.attr("cy", function (d) { return yScale(d.y); })
.attr("r", 6)
.style("fill", 'red')
.on('mouseover', function(d){
d3.select(this).style("fill", 'black');
d3.select('#myLines').selectAll("line").attr("class","sweepline").style("stroke", 'green');
})
.on('mouseout', function(d){
d3.select(this).style("fill", 'red');
});
As with many d3 problems this one is easily solved using data binding. Your custom colors could be bound to the lines you append to the second SVG. Since your array myColors, consisting of the arrays of custom colors per line, has the same structure as your other arrays like names, x1Val, y1Val and so forth, it can be easily integrated in the data array coords used for binding information to your lines:
var coords = d3.zip(names, x1Val, y1Val, x2Val, y2Val, myColors);
This data per line can later on be used in the mouseover event handler for your circles setting the stroke style on the lines.
.on('mouseover', function(d,i) {
// ...
d3.select('#myLines')
.selectAll("line")
.style("stroke", function(d) {
return d[5][i].color;
});
})
The callback determines the color by
accessing the array of custom colors, which is at position 5 of the data array bound to the lines, hence d[5],
getting the ith object of this array of colors. The i is the index of this circle, which is passed as parameter to the event handler and made available to the stroke callback by a closure,
getting property .color from this object
Check the updated JSFiddle for a working example.
Furthermore, I have updated the mouseout handler to delete the previously set stroke style causing the lines to be reset to their default color set by class sweepline. This behaviour, at least to my eyes, seemed to be missing.
d3.select('#myLines')
.selectAll("line")
.style("stroke", null);
I am making an interactive D3.js visualization with popup/tooltips to the data points so that on a mouseover event, a popup will appear next to the selected point with some information
Currently I have achieved this with the code below - the tooltip appears on mouseover. When the user moves the mouse to another point, the original tooltip disappears and the correct tooltip appears next to the new data point.
However, the mouseout event is not functioning as it should - the tooltip is not disappearing once the mouse leaves the datapoint. If the user does not move the mouse over a new data point, for example, the old tooltip remains there.
Relevant bits of code:
svg.selectAll("path")
//other stuff here
.on("mouseover", function(d) {
div.transition()
.duration(200) //mouseover transition does not seem to work, but that's minor
.style("opacity", .8);
div .html(d.datetime.substring(0,10) )
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 24) + "px")
.attr("display", display);
})
.on("mouseout", function(d) {
div.attr("display", none);
})
//bit of code where I append the tooltip to the right element
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", .8);
});
What am I doing wrong?
Thanks!
none is a string. So you have to enclose it in quotes. Also note that display is a css style attribute. So it should be applied as shown below.
div.style("display","none");
Other alternative options for implementing the same are the following.
Option 2:
div.attr("hidden",true);//to hide
div.attr("hidden",null);//to show
Option 3:
div.style("opacity",0);//to hide
div.style("opacity",1);//to show
Here is a working code snippet.
var button = d3.select("body")
.append("button")
.text("Mouse Over Me");
button.on("mouseover",function(){
div.style("display","block");
});
button.on("mouseout",function(){
div.style("display","none");
});
var div = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("display", "none")
.text("Hello This is a sample");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
display is not an HTML attribute, this is CSS. You need to change your code to something like this if you want to hide the element:
div.css({ "display": "none" });
Or just use the jQuery shortcut: div.hide();.
I would like to use hide() or show(). change from
div.attr("display", display);
to
div.hide();
here is the comments from .hide() or display: none? jQuery
"The matched elements will be hidden immediately, with no animation. This is roughly equivalent to calling .css('display', 'none'), except that the value of the display property is saved in jQuery's data cache so that display can later be restored to its initial value. If an element has a display value of inline, then is hidden and shown, it will once again be displayed inline."
This looks like you are following the tutorial here, right down to the extra space before the .html in the mouseover event. (Which is fine...the only reason I recognized that little syntax is because I spent all day staring at it!)
http://www.d3noob.org/2013/01/adding-tooltips-to-d3js-graph.html
You post the relevant code above, but are you also selecting the div that you want to operate on using the select method? This may be why your transition isn't working the way you want it to.
eg:
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
otherwise or in addition the proper way to get the tooltip to go away is as Gilsha answered above with this line on mouseout:
div.style("display","none");
I'm trying to teach myself D3 with examples from http://bl.ocks.org/mbostock.
I took the scatterchart and I'm trying to load various data depending on what menu-item is active.
Everything is working fine, but I got one problem I just can't solve.
The xAxis should update itself depending on the values from the data linked to the menu item.
I was searching the web for an answer, but couldn't find one that worked for me.
I think the problem (and solution) lies in this part of the code;
function updateChart() {
svg.selectAll('.dot')
.transition()
.duration(1000)
.attr('cx', function(d) {
return x(d.data[parameter]);
})
svg.select(".x.axis")
.call(xAxis);
}
I made this JSFiddle to make it more understandable.
Here's what's going on.
You successfully generated your xAxis with the correct x scale in the first go around, however
You didn't update your xAxis with the new domain of data
You were right in that you had to re-update your scales whenever you click on your labels.
I've done a couple of things:
Add a sourceData variable after you've coerced your numbers, for all your functions to reference
Add a updateXScale(data) function that will simply update your x scale's domain
Have it called every time you click a label. Not only will this fix your x scale, it will also enable the correct scaling of your x-coordinates for your .dot's.
Here's what it looks like all together. I've created a fiddle that has a working version of your example.
And here's your updateChart function for reference:
function updateChart() {
updateXScale(sourceData);
svg.selectAll('.dot')
.transition()
.duration(1000)
.attr('cx', function(d) {
return x(d.data[parameter]);
});
svg.select(".x.axis")
.call(xAxis);
}
I'm relatively new to D3, svg, and javascript in general, so please bear with me :]
I have been experimenting with D3 for creating plots and graphs. I have created a small plot using D3 and have been attempting to make it compatible with IE8. Here is a link to the more-or-less working build of my graph.
http://jsfiddle.net/kingernest/YDQR4/1/
After some research, I quickly realized that the only way running D3 on IE8 would be at all feasible is by using other APIs in conjunction with D3. Luckily, I found that someone had already put in some work into a project called "r2d3" which, from my understanding, uses raphael to paint the canvas on the IE8 window instead of using SVG (which apparenly was not supported in IE8).
I have been able to get items drawn on the screen, which is half the battle. However, I'm having many issues, particularly with my tooltip. My tooltip is written as a DIV container that floats and changes position/opacity on hover of the data circles. This seems to work fine in other browsers, but with r2d3, I have not been able to get it working. I suspect this is because of the fact that I am creating the div tooltip outside of the (in the #main div). However, I have tried placing tooltips inside of the SVG container with no avail. I then did more reseach and discovered I would have to wrap a div container inside a tag, but after some experimentation with this, I still wasn't able to get the tooltip to work correctly in IE. I attempted to wrap the in a SVG group (), and altered the positioning of this object instead, but this did not seem to work either, and simply through numerous exceptions when trying to append the foreignObject tag to a group.
At this point I'm sort of stuck, and was wondering if anyone had any suggestions as to how I may be able to successfully implement the tooltips. I've also noticed that using d3.select(this) inside my functions, when attempting to select a particular data point (in this case, a circle) seems to present a number of issues when attempting to access or modify that item's attributes, but I think this is a whole other issue entirely.
Any help is greatly appreciated!
Example of how I'm currently creating the tooltips:
//Create tooltip element
var tooltip = d3.select("#main")
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("opacity", 0);
function mousemove()
{ //Move tooltip to mouse location
return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");
}
//Mouseover function for circles, displays shortened tooltip and causes other circles to become opaque
function mouseover()
{
var myCircle = d3.select(this);
d3.select(this).attr("class", "dataCircleSelected"); //Color circle green
tooltip.html( //Populate tooltip text
"Username: " + d3.select(this).attr("username") + "<br/>" +
"Session ID: " + d3.select(this).attr("sessionid") + "<br/>" +
"Impact CPU: " + d3.select(this).attr("impact")
)
.transition()
.duration(250)
.style("opacity", .7);
//After 1000ms, make other circle opaque
svg.selectAll("circle")
.filter(function(d, i){ //return every other circle
return !d.compare(myCircle[0][0].__data__);
})
.transition().delay(1000)
.style("opacity", .2);
}
Have you tried using foreignObjects AND explicitly using the xhtml namespace for html tags in the foreignObject (write xhtml:div instead of div) as explained here: HTML element inside SVG not displayed ?
This would give something like that for the tooltip definition
var tooltip = d3.select("#main").append("foreignObject")
.append("xhtml:div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("opacity", 0);