When you chain transitions with a small duration, sometimes it skips the first one. It is not consistent. Sometimes 10ms doesn't work, but 5ms does. I used a setInterval with random duration in my demo so hopefully it will trigger for everyone http://jsfiddle.net/83rEC/. The code in question:
.attr('fill', 'red')
.style('opacity', 0)
.transition()
.duration(duration)
.style('opacity', 1)
.transition()
.attr('fill', 'green')
When that duration starts to get in the <10ms range is when it starts failing. Is it a bug in D3 or a logic failure on my part?
browser timing loops are typically 16.667 ms. Any time less than that is likely to be subsumed by the next event.
Related
I am using d3js collapsible tree.
https://bl.ocks.org/mbostock/4339083
How to make link blink(flash)? Can nodes also be made to show/hide at regular interval? I hope it can be done without using setInterval.
Thanks in advance
To make the links "blink" you'll want to use a transition. Honestly there's nothing wrong with setInterval, in fact I'd probably use it for ease.
Firstly you want the animation. It'd difficult to know what you mean by "blink" so I'm going to assume gets brighter for now - but you can change this up however you wish.
d3.select("svg")
.selectAll(".link")
.transition()
.duration(500) // miliseconds
.style("stroke", "white");
This will gradually change the style to white over a period of 500ms. Now you need to revert the color back to the original. You can do this using the end event on the transition object.
.on("end", function() {
d3.select(this).style("stroke", "#CCC");
});
Note that in the above this is the HTMLElement that the transition was running on. You can do this with a lambda (arrow function) if need be but you need to do (d, i, elements) => d3.select(elements[i]);
Now you've got you're transition, which resets. But you want to call it regularly. Honestly, the easiest way to do this is using setInterval... So your final code would look like:
// Create the regular interval
setInterval(() => {
d3.select("svg")
.selectAll(".link")
.transition()
.duration(500) // miliseconds
.style("stroke", "white")
.on("end", function() {
d3.select(this).style("stroke", "#CCC");
});
}, 1000);
This question might be really simple but for some reason I can't figure it out, or find anything online about it.
I create the following dashed lines like so:
linkContainer.enter()
.append("line")
.style("stroke-dasharray", ("3, 3"))
.attr("class", "link")
.on("click", clickLine);
What I want to do, is when the line is clicked, I want to change it back to a continuous line, i.e. no more dashes.
function clickLine() {
d3.select(this).transition()
.duration(750)
.style("stroke", "lightsteelblue");
}
Is there any style feature to transition the line from dashed to continuous? Thanks again in advance.
For a transition, I would modify the stroke-dasharray value to contain no gaps anymore -- the first number is the (relative) length of the dash and the second of the gap. So all you need to do is set the second number to 0:
d3.select(this).transition()
.style("stroke-dasharray", "3,0");
Complete demo here.
Been playing with D3 for a few days. I got a world map drawn, and some "events" with geo that are displaying on the map.
Each event is compsosed of longitude,latitude,date
The date ranges is from june 1st to August 31st.
When event are added to map as time progress, I have a plain circle. However, I would like to achieve a nice glowing effect, to emphasis the current geo point being an event. (example here : https://www.youtube.com/watch?v=ssbQ2PVxGng )
So far I have come with:
svg.append('svg:circle')
.attr('cx', coordinates[0])
.attr('cy', coordinates[1])
.attr('r', 4)
.transition('next', function() {
d3.select(this)
.duration(300)
.attr('r', 7)
.attr('fill', 'yellow')
.attr('fill-opacity', .3);
})
.attr('fill', 'orange');
But I have no luck so far.
I have a application where I draw a world map with D3 and I use latitude and longitude data from a different source to plot them on the map. Currently what I learnt from lot of google'ing is that i can plot points by appending "circle" to to the SVG, which works fine for first 15 to 20 seconds after my web page is opened, later everything gets too slow and sloppy.
I am not sure how to keep the performance of the page decent and not add a new DOM element for every single circle I append with SVG. Do I need to use some other technology to achieve this ? Please advice.
My code looks like below and I call this like 500 times every 5 seconds.
function draw_point(lat, lon, keyword) {
var x = projection([lon, lat])[0];
var y = projection([lon, lat])[1];
svg.append("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 0.5)
.style("fill", "gold");
svg.append("text")
.text(keyword)
.attr("x", x)
.attr("y", y)
.style("fill", "gold")
.style("font-size", "10px")
.transition()
.duration(40)
.style("opacity", 0)
.remove();
}
To give a bit more context, I am trying to do something like this site http://tweetping.net/ In this page I see that new DOM element is not being added for every dot placed in the map, I am looking for something similar.
The page which you mentioned uses canvas element and not svg or d3.js. You might want to look into
fabricjs
paperjs
kinectjs
Additional clarification of #VivekKumarBansal's suggestion: The general rule is that SVG slows down as more elements are added, but making images larger or smaller doesn't affect speed. Canvas doesn't slow down as more elements are added, but increasing size does slow it down. d3.js can be used with Canvas, although it seems to be more common to use it with SVG.
In the process of learning D3.js.
Is it possible using a force layout to place a circle within another circle shape as per the picture. I am hoping to transition between a single circle per node to a display showing two circles per node. The size of the effective donut is used to illustrate another variable in the data.
Is this possible?
You don't even need to use anything other than a basic svg circle, as you find in most examples. Just bind the data to it, apply a stroke, and set the stroke-width attr to your other variable. Or r - otherVar, I'm sure you can figure that part out.
If this doesn't satisfy, build your own shape. The 'g' svg element is a container element, and lets you build whatever you like. Add two circles to a g, fill them how you like. Make sure to add them in the right order, since svg has no concept of 'on top', things just get painted in the order that you add them.
edit: okay, quick demo so you can learn some syntax. I didn't add any comments but hopefully the code is very verbose and straightforward. Find it here.
d3/svg is something that you have to just bash your head against for a while. I highly recommend spending some time creating a sandbox environment where you can quickly test new things, save, refresh browser to see results. Minimizing that turnaround time is key.
Thanks to roippi I was able to create a group containing two circle shapes.
var nodeCircles = svg.selectAll("g")
.data(nodes);
// Outer circle
var outer = nodeCircles
.enter()
.append("circle")
.attr("class", "node_circle")
.attr("r", function(d) { return d.radius_plus; })
.style("fill", function(d) { return d.color_plus; })
.style("opacity", 0);
// Inner circle
var inner = nodeCircles
.enter()
.append("circle")
.attr("class", "node_circle")
.attr("r", function(d) { return d.radius; })
.style("fill", function(d) { return d.color; })
.style("stroke", function(d) { return d3.rgb(d.color).darker(2); })
.on("mouseover", mouseOver)
.on("mouseout", mouseOut)
.call(force.drag);
Outer circle visibility is toggled via a button.
As mentioned, I use a desktop based IDE to run/test visualisation languages. Currently the IDE supports studies written in D3.js, Raphael, Processin.js, Paper.js and Dygraphs. Picture below...