Concentric colours on D3 Sunburst diagram - javascript

I have a Sunburst diagram which uses essentially the same code as the standard at http://bl.ocks.org/kerryrodden/7090426 .
However, I have many many 'nodes' in my final two rings and any combination of colours makes it look extremely messy. As each node within the diagram is pulled from a database I'm unable to assign specific colours to values as the values are all unique.
Is there a way that I could specify a colour for the entirety of each individual ring in the diagram? As an example, I would like it to look somewhat like this:
http://www.design-by-izo.com/wp-content/uploads/2011/02/Krakow-3.jpg
That way I would be able to come up with a palette that doesn't clash as much as applying range of colours that d3 just cycles through.

From what I understand, you can simply change the fill style in the diagram, using depth of the respective data, like so:
.style('fill', function (d) {
return color(d.depth);
})
where color is some sort of a color array.
Alternatively, ES6/2015, just:
.style('fill', d => color(d.depth))
Here's a fiddle, showing you the effect: Fiddle
(based on this)
I hope this is what you want.

Related

D3 sunburst sequence colors and sunburst arc colors not matching

I am working with a zoomable sunburst in D3 that also has some breadcrumbs. First time working with D3 so I don't know all of the intricacies yet, but I am having trouble getting the colors of the arcs in the sunburst and the breadcrumbs in the sequence to match up. It only ever happens on the leaf nodes too which is weird. I can click on the inner circle and the breadcrumb shows up with the same color, and so on until I click on a leaf node.
Originally I set the color like this var colors = d3.scale.category10(); and the in the chart options like color: colors, When trying to set the colors for the polygon for the bread crumb I thought it'd be as simple as this which I had seen from a few examples,
entering.append("svg:polygon")
.attr("points", breadcrumbPoints)
.style("fill", function(d) {
return colors(d.name);
});
But this results in the explanation above. So to clarify in the picture below, either the outer arc on the sunburst should be pink, or the lowest bread crumb should be red. (I'm not sure which is correct, probably the former):
I have a working plunker I am almost done with, but can't get this part. Also part two kind of, but is it possible to set the color of individual arcs based on a certain value?
EDIT Okay well after looking at some more examples, it appears the red on red is okay in the picture for example. So I guess the solution I am looking for is to correct the behavior of the breadcrumbs.

Linking two elements on mouseover and dual tooltips

I'm looking for some advice on how to get two elements in a visualization, which are linked by a common data value, to respond simultaneously.
Here is the visualization as it stands now.
http://bl.ocks.org/natemiller/2686e5c0d9a1a4bb0895
Note that the different colored points are for the 50 US states in 2005 (green) and 2013 (blue), so there is a blue point and a green point for each state. I have two things I would like to get working here.
I would like to be able to mouseover either a blue point or a green point and have the corresponding point (for the same state) highlighted.
I would like a tooltip with some basic data to appear next to both points, providing point specific data.
Regarding the first point above. Right now when you mouseover a blue point the corresponding green point is highlighted, however, when you mouseover a green point only that point is highlighted and not its corresponding blue point. I imagine this is a simple fix, but for the life of me I can't figure out to reverse the reference so I get green to blue references as well.
Regarding the second point. Right now a tooltip with relevant information appears near the moused-over point, but I would like to have a similar tooltip appear next to the corresponding point from the alternate year of data, so that direct comparisons across years are easier. I am quite new to adding HTML tooltips so I'm not clear on how to do this and suspect it may require a new method for adding tooltips. Can any help to steer me in the correct direction for how to have a tooltip appear near the moused-over element and a corresponding linked element?
1) Remember that ids are unique and you're creating multiple circles with the same id, use a class instead
circles.attr("class", function(d) { return d.state })
2) You're creating a single tooltip, if you want to show one for each pair of states create multiple tooltips
Assuming that you make these changes you can easily create multiple tooltips for each pair of states
circles.on('mouseover', function (d) {
// selection for 2 states
var states = d3.selectAll('circle.' + d.state)
// code to style those nodes goes here ...
// tooltips for the states
var tooltips = d3.select('svg').selectAll('text.tooltip')
.data(states.data())
// initial styling of the tooltips goes here...
tooltips
.enter()
.append('text')
.attr('class', 'tooltip')
// update
tooltips
.html(function (d) {
// text of the tooltip
return 'something'
})
// positioning, it requires some margin fixes I guess
.attr('x', function (d) { return xScale(d.child_pov) })
.attr('y', function (d) { return yScale(d.non_math_prof) })
})
Finally remove the tooltips created on mouseover when the mouseout event is triggered
circles.on('mouseout', function (d) {
d3.select('svg').selectAll('text.tooltip').remove()
})
You cannot have multiple elements with the same id. Use a class .circleHawaii instead of an id #circleHawaii.

API or tutorial for the use of x3dom in d3.js?

If there's no existing tutorial/wiki, then I'm willing to create one. I've seen the d3.js examples of scatterplot, the 3d cubes, the awesome 3d svg example, 3d force layout and 3d bar graph, but am having a hard time figuring out how to get x3dom syntax translated to d3 syntax.
I've tried making the 3d bar graph an emissive surface like so and it works:
shapesEnter
.append("appearance")
.append("material")
//.attr("diffuseColor", '0.41 0.39 0.03' )
.attr("emissiveColor", '0.41 0.39 0.03')
//.attr("ambientIntensity", '0.0243902' )
.attr("shininess", '0.12' )
.attr("specularColor", '0.94 0.72 0' );
But when trying to apply textures (after commenting out the above code), it doesn't work:
shapesEnter.append("ImageTexture").attr("url", "file:///image1.png").attr("repeatS", "true").attr("repeatT", "true");
My questions are:
1. About how to figure out the x3dom equivalent syntax in d3?
2. How do I get a texture onto the 3d bar? (objective is to have a colour gradient on the bar, and texture seems to be the only way to do it)
D3 is a library to create and manipulate DOM elements based on data. Other libraries can manipulate DOM elements as well, the difference between D3 and other libraries is that D3 bind data elements to DOM elements. If you have a div with ID chart, you can append a x3d element to it and set its attributes:
var div = d3.select('#chart'),
chart = div.append('x3d')
.attr('width', '500px')
.attr('height', '400px');
This will modify the DOM structure of the page:
<div id='chart'>
<x3d width="500px" height="400px"></x3d>
</div>
You can append scenes and transformations using the reference to chart:
// Create the scene ans transform, and set their attributes
var scene = chart.append('scene'),
transform = scene.append('transform');
Until now, you have just manipulated the DOM, but D3 becomes more interesting when you bind selections to data. Let's say we have an array with the definitions for some shapes:
var deg = ['boxShape', 'sphereShape', 'cylinderShape'];
// Create a selection for the shapes that will be created and bind the selection
// to the array of colors
var shapes = transform.selectAll('shape.main-shape')
.data(colors);
// Append the shapes on enter and set some attributes
shapes.enter().append('shape')
.attr('class', 'main-shape');
// Update the 'def' attribute of the shapes, using the contents of the bound array
shapes.attr('def', function(d) { return d; });
I don't know the details about why the texture is not working, but I would recommend to inspect the generated code using the Web Developer Tools of the browser and see if the generated markup is different that you expect. If you can create a jsFiddle with a simple example, it would be easier to help you with the textures. There is a great tutorial on D3 by Scott Murray, to learn the details on data binding and selections. Regards,

Interactions that affect multiple separate charts in d3.js?

I'm trying to create a data visualization in d3.js that contains two charts: a parallel-axis plot, and horizontal colorbar chart (I just made up that name, but it's basically a series of colored rectangles). Each line in the parallel-axis plot is associated with a set of rectangles in the colorbar chart.
Right now, mousing over a given line highlights that line, and mousing over a given rectangle highlights that set of rectangles. My goal is to also highlight the associated line or set of rectangles on the opposite chart anytime the user mouses over either chart. This seems like it would be pretty straightforward if I generated both charts with the same function. However, it would be much neater (and more reusable) coding style to give each chart its own function and just connect them somehow. I tried having each within-chart mouseover function call a function defined at a higher level that affected both charts, but this didn't seem to have any effect on the chart that wasn't moused-over. Since I still don't feel like I fully understand how d3.js works on an underlying level, I'd really like to have confirmation that this is a viable way to set up my code. My code is long and complicated, and I really just want advice on the structure, so here is the basic outline:
function chart1(){
make chart
function mouseover(d,i){
do stuff
chart1_globalmouseover(d,i);
}
chartElement.on("mouseover", function(d,i){mouseover(d,i)});
}
function chart2(){
make chart
function mouseover(d,i){
do stuff
chart2_globalmouseover(d,i);
}
chartElement.on("mouseover", function(d,i){mouseover(d,i)});
}
function chart1_globalmouseover(d,i){
do stuff in chart 2's mouseover function
}
function chart2_globalmouseover(d,i){
do stuff in chart 1's mouseover function
}
c1 = chart1();
c2 = chart2();
One way to link the two graphs independent of the code used to create them would be to assign IDs or classes to the elements you may want to select. That is, if graph 2 has an element with ID foo, then in a mouse handler for an element of graph 1, you could say d3.select("#foo").style("stroke", "red") for example. Similarly with classes.
This approach allows you to keep the code completely separate. Moreover, if you use classes, you can assign the same class to things you would want to highlight together (e.g. elements representing the same data). Then d3.selectAll(".class") would select and allow you to manipulate all of them. This would work for an arbitrary number of graphs, not just two -- what changes is simply the number of elements that will be selected.

missing segments in d3 when putting sunburst on top of pie

(first posted on google group but no response so assuming I should be posting this here).
Am trying to lay a sunburst (coloured arcs) on top of a pie (yellow and white segments).
Here is a js fiddle that shows the problem, the initial green segments are missing:
http://jsfiddle.net/qyCkB/1/:
and a js fiddle without the pie where all the segments are shown correctly:
http://jsfiddle.net/X3sRy/1/
I have checked the nodes variable after it has been created on this line:
var nodes = partition.nodes({'values': data});
and the values appear to be the same in both examples.
On checking the DOM, it is just not drawing the first few segments of the sunburst.
Should this work or is it not possible to put two different layouts on top of each other?
Is there a better approach to achieving the same thing?
Your second-data join is colliding with the first. Your first data-join is on "g.arc", so you should be adding G elements with the class "arc" (not "clock_arc"). Your second data-join is on "path", which is inadvertently selecting the path elements you added previously. Since your second data-join matches the previously-added elements, you're not entering all of the expected elements for the pie.
You need to disambiguate the sunburst path elements from the pie path elements. One way you could do this is to select by class rather than element type, so the second data-join becomes ".pie" rather than "path". Something like this:
var gClock = svg.selectAll(".clock")
.data(clockData)
.enter().append("g")
.attr("class", "clock");
var pathClock = gClock.append("path");
var pathPie = svg.selectAll(".pie")
.data(pieData)
.enter().append("path")
.attr("class", "pie");
I'd also recommend reading these tutorials, if you haven't already: Thinking with Joins, Nested Selections, Object Constancy.

Categories

Resources