I'm plotting thousands of SVG circle elements on chrome with d3, and am running into weird rendering issues. It seems that paths are being drawn between the circles. These elements have mouseover events, and when mousing over them, that small portion of the screen redraws and removes the weird paths from that area, but after mouseout, it goes back to the weird lines.
The expected behavior works on Safari, but nothing is drawn at all in Firefox.
I've had a hard time figuring out how to get this to work on Chrome. I previously made a smaller instance of the behavior disappear by removing the 'crispEdges' attribute in the circle's CSS, but that is not working anymore. Also, I have been able to successfully render these points in Chrome before- not sure why it's starting to act like this now.
Anyone have any ideas about why this is happening and what I can do to get this working on Chrome? Any input is greatly appreciated!
==============
Chrome Version: 56.0.2924.87
Safari Version: 10.0
JS code for drawing circles:
var xScale = d3.scaleLinear()
.domain([0, xMax])
.range([0, width - margin.right]);
var yScale = d3.scaleLinear()
.domain([0, yMax])
.range([height - margin.top, 0]);
var x = function(d) { return xScale(d.x); }
var y = function(d) { return yScale(d.y); }
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("cx", x)
.attr("cy", y)
.style("fill", colors)
.on("mouseover", function(d,i){
tooltip.html(toolTipHTML(d))
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
return tooltip.style("visibility", "visible");
})
.on("mouseout", function(d){
return tooltip.style("visibility", "hidden");
});
CSS:
circle {
fill: black;
stroke: none;
shape-rendering: auto;
}
In Chrome:
In Safari:
===========
EDIT: Small demo on Plunker
I was able to reproduce the issue once on plunkr, but then after refresh, it went away. I tried to add more data to get it to reproduce again, but received a '400- Bad Request' response from plunkr. Sometimes when you zoom in on the circles, the random 'extraneous lines' show up, but they go away randomly. Anyways, here's the code if it helps. The original issue I've explained above is still an issue, even after refreshing multiple times. Any thoughts on how to move forward with this is greatly appreciated!
==============
EDIT 2/9: This may potentially be a hardware issue.
I'm using a Macbook Air, early 2015; running macOS Sierra 10.12.
As I mentioned in the comments, I recorded a short video of the strange behavior that happens when I zoom into the Plunker demo, in case it gives a better description of the issue than I've been able to give with words alone:
https://www.youtube.com/watch?v=saAm6Rim0zw&feature=youtu.be
For anyone following this post, as of about 2 days ago, a bug was reported on Chromium by someone else with the issue (Chrome on Mac):
Chromium Bug Report
Related
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.
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 building an application in D3.js where I render several index cards (svg's) as one SVG. The user should be able to rotate those cards. For test purposes I used the drag behaviour for rotation
dragListener = d3.behavior.drag().on("dragstart", function(d){
originX = parseInt(d3.select(this).select("image").attr("x"));
originY = parseInt(d3.select(this).select("image").attr("y"));
})
.on("drag", function(d){
counter++;
if(counter > 360){
counter = 0;
}
d3.select(this).attr("transform",
"rotate("+counter.toString()+","+(originX+150).toString()+","+(originY+90).toString()+")");
});
which I provide to all index cards
var grp = svg.selectAll("g").data(arr);
var card =
grp.enter().append("g")
//.attr("transform", function(d){ return "rotate(30,"+(d.x+150)+","+(d.y+90)+")";})
.call(dragListener);
card.append("svg:image")
.attr("xlink:href", "http://images.clipartlogo.com/files/images/22/227702/index-card_p")
.attr("x", function(d){return d.x;})
.attr("y", function(d){return d.y;})
.attr("width", "300")
.attr("height", "180");
The problem is, the more cards are already rotated the lower the performance when the user rotates a card . The FPS are around 8 in Chrome when all cards are rotated.
Here is the example: http://jsfiddle.net/45hdjkk0/6/
You can give all cards an initial rotation by removing the comments in line 32.
Am I doing something wrong or did I choose the wrong approach?
UPDATE:
After testing the same example on the Internet Explorer and on Firefox I have found out that Internet Explorer is the fastest among those three. Firefox is also very fast compared to Chrome. Is this a Chrome issue?
Rotating any bitmap is computationally expensive. I ran your fiddle in Firefox and Chrome. Though Firefox wasn't too bad, I did see some of the frame-rate slowdown in Chrome you spoke of. There may not be a good solution if it has to be a png. If it doesn't have to be png, you will get great performance rotating an svg composed of your combined graphics elements.
Edit: It looks like you really do want to rotate index cards, so I think you are in luck. To illustrate what I'm talking about, comment out line 36 and then uncomment line 32. Then see the rotation performance without the bitmap. Then simply add in a few .attr("path", ...) lines to reproduce your index card and I bet the performance will rock.
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 have a d3 visualisation on a web page that shows a collection of plot points on a chart.
It's all very simple really with just two axis and sometimes maybe 30 points to plot. As I render these plots I perform a transition on the r attributes of the SVG circles. The code that does this is:
g.append("svg:circle")
.attr("class", "plot-circle")
.attr("cx", xCo)
.attr("cy", yCo)
.attr("r", 0)
.transition()
.delay(function() { return delayInput * 100; })
.duration(plotExplosionDuration)
.ease(Math.sqrt)
.attr("r", 6);
All that occurs is that the circles are initially set to r=0 which means they aren't rendered at all. Then I start a transition on the appended circle to take this radius up to 6.
The problem is that it appears on some machines these transitions don't stop at r=6 and some plots end up being much bigger than the value set after the transition.
I simply cannot duplicate this on my main development machine (PC), my iPad nor my MacBook Pro which leads me to think it might be performance or machine load causing this?
has anyone got any ideas on how to ensure the transition stops at the defined final r value?