I'm a freshman wordpress guy who tried to display my small d3.js portofolio collection at my new site built using wordpress. Upon doing so i encountered a small problem : i display my works in a specific blog page, which is accessed by clicking the 'Visual Blog' top navigation menu.
Among the articles is one titled 'Growth Domestic Products of Nations : Bubble Force Chart' which has d3.js visualization embed-ed in it. If you hover on a bubble, there suppose to be a tooltip appear which displays various info, which works fine until yesterday, after i added new articles titled 'British Monarch Family Tree : Force Directed Graph' on top of it, the bubble tooltip suddenly not displaying anymore on mouse hover event.
The tooltip still works fine if you access the article directly, however it doesn't when accessed in the blog page from top navigation menu, as described above.
Here is the relevant code snippet :
bubbles
.on("mouseover", function(d){
tooltip_div.style("display", "inline");
/*.....*/
})
.on("mousemove", function(d){
var r = this.getBBox().width/2, myX = this.getBBox().x, myY = this.getBBox().y;
tooltip_div
.style("left", function(){
return ((d3.event.pageX - 250)+ r) + "px";
})
.style("top", function(){
return (d3.event.pageY - 470) + "px";
});
})
.on("mouseout", function(d){
tooltip_div.style("display", "none");
/*.....*/
});
It is quite confusing, since i used the same technique to display and determine tooltip position at my other articles, such as the various 'Barchart' articles, they're all works fine, except for this bubble chart alone...
Note 1 : i tested this on Opera.
Note 2 : i tried to delete the 'British Monarch Family Tree : Force Directed Graph' article from the blog page, the tooltip back to normal. I posted it again, the tooltip not appearing again...
It seems imposible to rely on absolute tooltip positioning since a wordpress blog is always growing with new articles, messing with the d3.event.pageX and d3.event.pageY variables. Not to mention as a wordpress newbie, my knowledge about how wordpress system works is still lacking..
Instead of positioning the tooltip relative to the entire dynamic page itself (by means of d3.event.pageX and d3.event.pageY), i just append the tooltip directly onto the SVG on every mouse over, adjust the position using d3.mouse(this) as opposed to d3.event earlier, and delete the tooltip SVG element on mouse out event..
var countryText;
bubbles
.on("mouseover", function(d){
countryText = bubbleGroup.append("text")
.attr("class", "countryText")
.attr("font-size", 13)
.attr("font-weight", "bold")
.text(d.country)
.style("pointer-events", "none")
.attr("x", d3.mouse(this)[0] - 60)
.attr("y", (d3.mouse(this)[1] - 20));
})
.on("mousemove", function(d){
countryText
.attr("x", d3.mouse(this)[0] - 60)
.attr("y", (d3.mouse(this)[1] - 20));
})
.on("mouseout", function(d){
d3.select(".countryText").remove();
})
As you can see, this gives stable tooltip positioning wether if you see the article in the blog page, or if you access the article directly.
Related
I have a very strange behave in my angularjs application.
1) I'm using d3js to draw a nice bar chart
graphG.append("rect")
.attr("id", function (d, i) {
return "bar_" + i;
})
.attr("x", 0)
.attr("y", 0)
.attr("height", barHeight - 1)
.attr("width", function (d, i) {
return rectWidth(d, i);
})
.attr("fill", rectColor);
2) After a data update there is a transition
barG.select("#bar_" + i)
.transition()
.duration(duration)
.attr("fill", rectColor(d))
.attr("width", rectWidth(d, i));
So far the width transition works fine. The color transitions with gradient doesn't work, but this is an another question. It changes the color but without smooth transition.
If i reroute to another page and come back the rect will not be rendered any more. The rect is in the dom. Width attribute got changes. No bar.
After F5 reload every thing is fine again.
And more strange behave: it happens in Chrome, it works fine in Firefox.
Anybody some ideas?
I have found the problem:
the error was that the gradient id (return of rectColor function) was same in both directives. So it seems that there is some caching in Chrome.
Rename the gradient id in one directive fixes the issue.
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've generated a D3 visualization (a force directed graph) that requires zooming and panning. I've got 2 problems however when it comes to zooming, and I can't find any decent examples on how I might overcome these problems:
The first problem is I've followed all the examples I can find about zooming, which involves adding groupings and adding a rectangle to ensure that the entire area is zoomeable. If I style the rectangle a slightly opaque blue then I get SVG that looks like this when I zoom out:
The problem with this is that I can zoom in/out absolutely fine while I've got my mouse over the blue rectangle area. The problem is I want this to be fully opaque, which means that when I zoom right out, it's very easy to place the cursor outside of this box and then you're unable to zoom in. Is there a way I can make the SVG itself zoomeable or pick up on these events?
This is how I go about generating the various layers and the zoomed function:
function zoomed() {
group2.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
svg = d3.select(target)
.attr("pointer-events", "all")
.append("svg");
group = svg.append('svg:g')
.call(d3.behavior.zoom().on('zoom', zoomed))
.on("dblclick.zoom", null);
group2 = group.append("g");
rect = group2.append('svg:rect')
.style("opacity", 0.3)
.attr('width', width)
.attr('height', height);
The second problem I have is that I'm trying to automatically size my text based on this http://bl.ocks.org/mbostock/1846692 example. When I've tried this however I seem to be getting text that renders really poorly. It seems to suffer from:
Being difficult to read
Not appearing contained within the circle
Being so small the entire thing compresses (image 2)
var texts = planets.append("text")
.text(function(d) { return d.name; })
.style("font-size", "24px") // initial guess
.style("font-size", function(d) {
return Math.min( 2 * d.size, (2 * d.size - 8) / this.getComputedTextLength() * 24) + "px";
})
.attr("dx", function(d) { return -d.size; })
.attr("dy", ".35em")
.style("fill", "white");
I thought that SVG would just handle this, I understand that some of the font-sizes can come out small, but if you zoom in should that not all sort itself out?
I've got a JSFiddle http://jsfiddle.net/IPWright83/vo7Lpefs/22/ to demonstrate.
I've not yet managed to work out a resolution to my first issue (regarding the zooming box) however I did manage to track down the text rendering issue.
This was actually because the each circle/node had a stroke property to provide the white border. This was also applying to the text element, and when the font was very small the stroke was much larger than the overall fill of the text. Removing the stroke from the text elements ensured that they rendered even when very small.
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);
How do I implement tooltips on mouse over for links in a D3 directed graph layout? I'm adapting the D3 force example, so setting up node tooltips was straightforward using code like this:
node.append("title")
.text(function(n) {
return n.id;
});
Trying a similar technique with the links didn't result in mouse over tool tips:
var link = svg.selectAll("line.link")
.data(json.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) {
return 4;
});
link.append("title")
.text(function(n) {
return n.info;
});
You can find different solutions suggested by Mike Bostock on this Google Groups thread "show value when click or move mouse over on d3.svg.line"
I think what you are looking for is a combination of these two answers:
d3js: _on()_ doesn't send the current datum object to the onmouse function
and
Adding tooltip to bar chart generated using svg path
Both have jsFiddles you can play with.
Setting the link title as shown above does result in mouse over tooltips -- iff you let the mouse hover over any portion of the link a couple of seconds.