I have prepared a bubble chart , which you can zoom into using the brush in ther grey area below the scale.Here is the fiddle. The code below updates the graph . It is updating the ruler but not graph. Can any one point out why?
function brushmove(){
x_axis.domain(brush.empty() ? x_axis.domain() : brush.extent());
svg.select('.ruler').call(x_axis_ruler);
blue_circle.selectAll('circle').data(dataset)
.attr('cx', function (d, i) {
return x_axis(d.waiting_to_be_processed_time);
})
}
I dont know why but you should not be using the variable blue_circle to update the width .
Instead you should be replacing the code with this:
function brushmove(){
x_axis.domain(brush.empty() ? x_axis.domain() : brush.extent());
svg.select('.ruler').call(x_axis_ruler);
d3.select('.processing_circles').selectAll('circle').data(dataset).attr('cx', function (d, i) {
return x_axis(d.waiting_to_be_processed_time);})
}
I have left the reason for a more experienced user to checkout.
Related
I am using the d3 zoom behaviour and attempting to use a transition for both a translateTo and a scaleTo at the same time. If I make the calls to zoom without a transition everything works fine. If I use a transition for just one of the transforms it also works, but if I attempt to use a transition for both it fails (it appears to only apply the first transform). I have a JSFiddle with several combinations here: JSFiddle
Here's the code that isn't working as I expect
svg.transition()
.duration(750)
.call(zoom.scaleTo, 2)
.call(zoom.translateTo, 50, 50)
You can do like this:
svg.transition()
.duration(750)
.call(zoom.scaleTo, 2)
.transition() <--- this is missing.
.call(zoom.translateTo, 50, 50)
First zoom then translate.
working code here
EDIT
Performing zoom and translate both # same time you need to tween.
function twizzle(selection, duration) {
d3.select(selection).transition()
.duration(duration)
.tween("attr:transform", function() {
//interpolate from start to end state
var i = d3.interpolateString("scale(1)translate(0,0)", "scale(2)translate(50,50)");
return function(t) {
selection.attr("transform", i(t));
};
});
}
Now call the function like this:
d3.select('body')
.append('button')
.text('transition both - scale first')
.on('click', function() {
//on click call the function created above
group.call(twizzle, 750) <-- perform the scale and translate on the group not on the SVG.
})
working code here
I'm building a number of graphs using crossfilter and dc.js. Among others, there is a row chart and an histogram (a bar chart).
What I am trying to do is to create a tooltip on the row chart which will show the histogram.
Looking at this SO-question I saw an example using d3-tip. I have made an attempt in this jsfiddle. However, I cannot see how to embed a div in the tooltip.
Any suggestion? (If using plain d3 is better, I'm ok with that.)
Snippet of code is:
function draw_row(div_id){ ...; return row_chart; }
function draw_hist(div_id){ ...; return bar_chart; }
var rate_chart = draw_row('#rate').title(function(){return'';});
dc.renderAll();
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function () {
// What to put in here???
draw_hist('#distr').render();
return "<div id='distr'>Distribution<br></div>"
});
d3.selectAll("#rate g.row")
.call(tip)
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
Fun project!
Yes, as you noticed, you're not going to be able to render the chart while you're in the .html() callback - that only returns static HTML, and I don't think you can give it an element instead.
So we'll have to find a place to render after the HTML has already been generated. Luckily, d3-tip doesn't try to handle mouse events or anything like that - the code which displays the tip is right there in the code you've posted:
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
So we can wrap tip.show in a function of our own, and then render the chart into the tip once it's on the screen.
We have to watch out because mouseover will fire every time the mouse moves, and we probably don't want to replace the tip-chart until we hover over another bar. So we'll remember the id of the last bar we hovered:
var last_tip = null;
d3.selectAll("#rate g.row")
.call(tip)
.on('mouseover', function(d) {
if(d.key !== last_tip) {
tip.show(d);
draw_hist('#distr').render();
last_tip = d.key;
}
})
.on('mouseout', function(d) {
last_tip = null;
tip.hide(d);
});
Finally, d3-tip needs to know the size of the tip content in order to render in the right place. (If it accidentally renders on top of the element, this can cause horrible flickering when the mouse goes over the tip, registering mouseout on the element.)
So we'll just hard-code that, since we're hard-coding the chart size anyway. 20 extra pixels to fit the title:
.html(function (d) {
return "<div id='distr' style='min-width:300px; min-height: 320px'>Distribution<br></div>"
});
Looks pretty cool with the default translucent black style from d3-tip:
Here's the fork of your fiddle: https://jsfiddle.net/gordonwoodhull/hkx7j3r5/10/
I am working on the line graph using brush and context see this link for what I have so far. The brushing effect is only appearing on the scale and not the line graph. I am not able to figure out how to change brushed() function so that the brushing also appears for the line chart as well.
function brushed(){
console.log("brush called");
x.domain(brush.empty() ? x1.domain() : brush.extent());
focus.select(".line").attr("d", line);
focus.select(".x.axis").call(xAxis);
}
I needed to rewrite brushed function to following to update the line chart.
function brushed(){
console.log("brush called");
x.domain(brush.empty() ? x1.domain() : brush.extent());
**focus.selectAll(".line").attr("d", function(d) { return line(d.values); })**
focus.select(".x.axis").call(xAxis);
}
updated plnkr link
Introducing
I'm using Sequences Sunburst of d3.js for visualization of data.
I want to add a transition between two datasets (triggered by a button). I would like each arc to animate to display the new data.
Something like this: (1)Sunburst_Exemple, but without changing the accessor.
Research
In the (1)Sunburst_Example, the value accessor is modified. But I want to change the data, not the function that defines how to reach the data.
So, I searched a way for redefining data into path.
I was inspired by (2)Sunburst_Exemple, using each() method to store old values and attrTween() for transitions. But nothing is changing and I have the following error message:
Maximum call stack size exceeded . Maybe caused by the fact I have a method and I'm not in a global scope.
(2) link : _http://ninjapixel.io/StackOverflow/doughnutTransition.html
Then I have tried (3)Zoomable_Sunburst example, but nothing it happens in my case... .
(3) link : _http://bl.ocks.org/mbostock/4348373
My Example
Here is my example : JSFIDDLE
Problem is :
colors are lost
transition is not happening
I think I don't understand how transitioning is really working, I could have missed something that could help me in this case.
Any help ?
-
Listener of button call click method that redefined nodes and path.
/*CHANGING DATA*/
function click(d){
d3.select("#container").selectAll("path").remove();
var nodes = partition.nodes(d)
.filter(function(d) {
return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
}) ;
var path = vis.data([d]).selectAll("path")
.data(nodes)
.enter().append("svg:path")
.attr("display", function(d) { return d.depth ? null : "none"; })
.attr("d", arc)
.attr("fill-rule", "evenodd")
.style("fill", function(d) { return colors[d.name]; })
.style("opacity", 1)
.on("mouseover", mouseover)
.each(stash)
.transition()
.duration(750)
.attrTween("d", arcTween);
;
// Get total size of the tree = value of root node from partition.
totalSize = path.node().__data__.value;
}
_
// Stash the old values for transition.
function stash(d) {
d.x0 = d.x;
d.dx0 = d.dx;
}
// Interpolate the arcs in data space.
function arcTween(a) {
var i = d3.interpolate({x: a.x0, dx: a.dx0}, a);
return function(t) {
var b = i(t);
a.x0 = b.x;
a.dx0 = b.dx;
return arc(b);
};
}
Data Characteristics :
the root node is the same for the two datasets.
the structure is globally the same, only the values are changing.
Some fields disappear but we can add them with value equal to 0.
I have multiple nvd3 pie charts in the same page. Now when I try to position them,individually using this code below
d3.select(".nv-pieWrap")
.attr("transform", "translate(0,-35)");
Only the first graph in the page gets repositioned. It is said in the nvd3 support document that the select keyword if used in multiple functions,only selects the first element in the page.
Now when I replace "select" with "selectAll",every graph is re-positioned.
I want to position them separately ie the "translate" coordinates would be different in different cases. How would I accomplish that?. Can anyone help?
d3.selectAll(".nv-pieWrap")
.attr("transform", "translate(0,-35)");
I've got two solutions of the problem.
One solution is you can specify 'transform' attribute not as a constant "translate(0,-35)" but a function instead. And within the function decide which coordinates you need based on the chart's index:
d3.selectAll(".nv-pieWrap")
.attr("transform", function(d, i) {
// i is a chart index
if (i === 0) {
return 'translate(0,-35)';
} else {
return 'translate(100,-35)';
}
});
Another solution is to wrap your code
d3.select(".nv-pieWrap")
.attr("transform", "translate(0,-35)");
into a transforming function which takes a node and transform as a parameter, e.g.
var transform = function(chart, transform) {
return
d3.select(chart)
.attr("transform", transform);
}
draw("#pieChart1", "translate(0,-35)");
draw("#pieChart2", "translate(100,-35)");