I'm accessing a GITHUB raw file and using the d3.pie() function making the start and end angles of the pie, at that point the data is showing on console but when I access it in tooltip it gives UNDEFINED.
Do run the code if you can, the link to my github is given where I'm loading my file d3.csv() also FUNCTION TEST is running only once I need to run it till my data runs out.
//CALCULATING RADIUS OF CHART
var radius = Math.min(width, height) / 2 - margin
//APPENDING SVG IN DIV HAVING ID pieChart
var svg = d3.select("#pieChart")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// DATA
d3.csv
("https://raw.githubusercontent.com/Dehya/django/master/pkpopulation.csv?
token=AHXLL23PHQSJGYIYCLA6YX25I7IJA",function(error, data){
// GETTING VALUES AS POPULATION FROM DATA AND CALCULATING THE START AND
END
ANGLE:
var pie = d3.pie()
.value(function(d) {return d.population; })
console.log(pie(data));
//SETTING COLOR SCALE
var color = d3.scaleOrdinal()
.domain(data)
.range(["red", "yellow", "green", "blue", "orange"])
function Test(d){
for( i ; i<data.length ; i++)
{
console.log(data[i].name + " : " + data[i].population);
return data[i].name + " : " + data[i].population;
}
}
//MAKING TOOPTIP
var tip = d3.tip()
.attr("class", "d3-tip")
.offset([-10, 0])
.html(Test(data));
svg.call(tip);
//MAKING SLICES OF PIE CHART
svg
.selectAll("mySlices")
.data(pie(data))
.enter()
.append("path")
.attr('d',d3.arc()
.innerRadius(0)
.outerRadius(radius)
)
.attr("fill", function(d){ return color(d.data.key) })
.attr("stroke","black")
.style("stroke-width","1px")
.style("opacity",0.7)
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
});
Related
My code is like this. Can you say what is the error? My color is not showing properly although the section text is showing. the data set is the death rate of the US over time.
function clicked(d,i) {
var dataset = [d.females, d.males];
var pcolor = ["green", "pink"];
var outerRadius = 60;
var innerRadius = 0;
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var pie = d3.pie();
//Easy colors accessible via a 10-step ordinal scale
//var color = d3.scaleOrdinal(d3.schemeCategory10);
//Set up groups
var arcs = svg.selectAll("g.arc")
.data(pie(dataset))
.enter()
.append("g")
.attr("class", "arcs")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");
//Draw arc paths
arcs.append("path")
.attr("d", arc)
.attr("fill", function(d, i) {
console.log(d);
return pcolor(i);
});
//Labels
arcs.append("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d) {
return d.value;
});
}
I create a multi ring donut chart following some examples on the web and everything was ok till i try to display text into the ring and got stuck with different errors.
I think at this point i can access data but i when comes to create rings, i got NaN values for my path and text.
Here is my code:
var dataset = {
ringOne: [{"label":"70%", "value":70},
{"label":"10%", "value":10},
{"label":"20%", "value":20}],
ringTwo: [{"label":"70%", "value":70},
{"label":"10%", "value":10},
{"label":"20%", "value":20}],
};
var width = 460,
height = 300,
cwidth = 45,
outerR = 100,
color = d3.scale.ordinal().range(["#07e", "#00aced", "#e32"]);
var svgDonut = d3.select("#donut")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")" );
var arc = d3.svg.arc();
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.value; });
var rings = svgDonut.selectAll("g.slice")
.data(pie([dataset]))
.enter()
.append("g")
.attr("class", "slice");
rings.append("path")
.attr("fill", function(d, i){ return color(i); })
.attr("d", function(d, i, j){ return arc.innerRadius( 80 + cwidth * j )
.outerRadius( outerR * (j) )(d); });
rings.append("text")
.attr("transform", function(d) {
d.innerRadius = 0;
d.outerRadius = outerR;
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d, i) { return dataset.ringOne[i].label; });
The error i get is:
Error: Invalid value for <path> attribute d="M4.898587196589413e-15,-80A80,80 0 1,1 NaN,NaNL0,0Z"
Error: Invalid value for <text> attribute transform="translate(NaN,NaN)"
fiddle here: https://jsfiddle.net/anaketa/8u7gejjc/
Any ideas?
I am trying to create an interactive sunburst diagram using D3, where the user can select a data source from a dropdown menu. Once the data source is selected, any existing sunburst would be erased and redraw using the new data. This is based off the D3 example called "Sequences Sunburst" http://bl.ocks.org/kerryrodden/7090426
Having done a bit of research, it looks like you need to follow the add/append/transition/exit pattern.
Here is a link to a semi-functioning example on JSFiddle: http://jsfiddle.net/DanGinMD/dhpsxm64/14/
When you select the first data source, the sunburst diagram is created. When you select the second data source, a second sunburst is added. Each one appears to be connected to its unique data source. How do I erase the first sunburst before drawing the second sunburst?
Here is the code for listener event for the dropdown box:
// an event listener that (re)draws the breadcrumb trail and chart
d3.select('#optionsList')
.on('change', function() {
var newData = eval(d3.select(this).property('value'));
createVisualization(newData);
});
Here is the code that draws the sunburst diagram:
function createVisualization(json) {
sysName = json.sysName;
var titletext = sysName + " - Impact to Organization";
d3.select("#title2").text(titletext);
initializeBreadcrumbTrail();
var vis = d3.select("#chart").append("svg:svg")
.attr("width", width)
.attr("height", height)
.append("svg:g")
.attr("id", "container")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var partition = d3.layout.partition()
.size([2 * Math.PI, radius * radius])
.value(function(d) { return d.size; });
var arc = d3.svg.arc()
.startAngle(function(d) { return d.x; })
.endAngle(function(d) { return d.x + d.dx; })
.innerRadius(function(d) { return Math.sqrt(d.y); })
.outerRadius(function(d) { return Math.sqrt(d.y + d.dy); });
// Bounding circle underneath the sunburst, to make it
// easier to detect when the mouse leaves the parent g.
vis.append("svg:circle")
.attr("r", radius)
.style("opacity", 0);
// For efficiency, filter nodes to keep only those large enough to see.
var nodes = partition.nodes(json)
.filter(function(d) {
return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
});
var path = vis.data([json]).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.category]; })
.style("opacity", 1)
.on("mouseover", mouseover);
// Add the mouseleave handler to the bounding circle.
d3.select("#container").on("mouseleave", mouseleave);
// Get total size of the tree = value of root node from partition.
totalSize = path.node().__data__.value;
path.exit().remove();
nodes.exit().remove();
arc.exit().remove();
partition.exit().remove();
vis.exit().remove();
}
Note the following call that appends a new svg at visualization initialization:
var vis = d3.select("#chart").append("svg:svg")
.attr("width", width)
.attr("height", height)
.append("svg:g")
.attr("id", "container")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
You just need to remove any old svg before this statement:
d3.select("#chart svg").remove();
var vis = d3.select("#chart").append("svg:svg")
.attr("width", width)
.attr("height", height)
.append("svg:g")
.attr("id", "container")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
fiddle
I'm very new to D3 - in fact I only started yesterday - have a donut pie chart here:
var dataset = new Array();
dataset[0] = {"value":"50","color":"red"};
dataset[1] = {"value":"20","color":"blue"};
var pie = d3.layout.pie().sort(null).value(function(d){return d.value;});
var h = w = 500;
var center = w / 2;
var outerRadius = ((h/2)-5);
var innerRadius = outerRadius-10;
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var arcOutter = d3.svg.arc()
.innerRadius(outerRadius)
.outerRadius(outerRadius + 1);
var arcInner = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(innerRadius - 1);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Set up groups
var arcs = svg.selectAll("g.arc")
.data(pie(dataset))
.enter()
.append("g")
.attr("class", "arc")
.attr("transform", "translate(" + center + ", " + center + ")");
//Set up outter arc groups
var outterArcs = svg.selectAll("g.outter-arc")
.data(pie(dataset))
.enter()
.append("g")
.attr("class", "outter-arc")
.attr("transform", "translate(" + center + ", " + center + ")");
//Set up outter arc groups
var innerArcs = svg.selectAll("g.inner-arc")
.data(pie(dataset))
.enter()
.append("g")
.attr("class", "inner-arc")
.attr("transform", "translate(" + center + ", " + center + ")");
//Draw arc paths
arcs.append("path")
.attr("fill", function (d, i)
{
return d.data.color;
}).attr("d", arc);
//Draw outter arc paths
outterArcs.append("path")
.attr("fill", 'green')
.attr("d", arcOutter).style('stroke', 'white')
.style('stroke-width', 0);
//Draw inner arc paths
innerArcs.append("path")
.attr("fill", 'green')
.attr("d", arcInner).style('stroke', 'white')
.style('stroke-width', 0);
jsFiddle chart
But I'm struggling to add 4 clock points and their time tables to it, (12am, 3pm, 6pm, 9pm), I've tried searching clock examples but they're all working clocks, not just the points.
I want it to look pretty much like this:
Any help would be greatly appreciated.
I don't know how aestheticaly correct it is, but here it goes. What you could do, is add 4 line segments in your chart at these locations:
[w/2, 0],[w/2,h],[0,h/2],[w,h/2]
You can achieve that if you add the following lines:
var x=d3.scale.linear().domain([0,outerRadius]).range([0,w])
var y=d3.scale.linear().domain([0,outerRadius]).range([h,0])
svg.append('line').attr("x1",x(outerRadius/2)).attr("y1",0).attr("x2",x(outerRadius/2)).attr("y2",20)
svg.append('line').attr("x1",x(outerRadius/2)).attr("y1",y(outerRadius)).attr("x2",x(outerRadius/2)).attr("y2",y(outerRadius)-20)
svg.append('line').attr("x1",0).attr("y1",y(outerRadius/2)).attr("x2",20).attr("y2",y(outerRadius/2))
svg.append('line').attr("x1",x(outerRadius)).attr("y1",y(outerRadius/2)).attr("x2",x(outerRadius)-20).attr("y2",y(outerRadius/2))
Please note that you have to create a css entry, so that the line is shown:
line{
display:block;
stroke:black;
}
JSFiddle here
Hope this helps
Following the lovely example here.
var radians = 0.0174532925;
var hourScale = d3.scale.linear()
.range([0,330])
.domain([0,11]);
var labelGroup = svg.append('g')
.attr('transform','translate(' + (center + margin) + ',' + (center + margin) + ')');
labelGroup.selectAll('.hour-label')
.data([12,3,6,9])
.enter()
.append('text')
.attr('class', 'hour-label')
.attr('text-anchor','middle')
.style('font-size','16pt')
.attr('x',function(d){
return outerRadius * Math.sin(hourScale(d)*radians);
})
.attr('y',function(d){
return -outerRadius * Math.cos(hourScale(d)*radians);
})
.text(function(d){
return d;
});
Updated fiddle.
I have a dynamic data source that creates a new json in the browser frequently.
I was able to create a pie chart from this json using the code below (also at this fiddle)
var data=[{"crimeType":"mip","totalCrimes":24},{"crimeType":"theft","totalCrimes":558},{"crimeType":"drugs","totalCrimes":81},{"crimeType":"arson","totalCrimes":3},{"crimeType":"assault","totalCrimes":80},{"crimeType":"burglary","totalCrimes":49},{"crimeType":"disorderlyConduct","totalCrimes":63},{"crimeType":"mischief","totalCrimes":189},{"crimeType":"dui","totalCrimes":107},{"crimeType":"resistingArrest","totalCrimes":11},{"crimeType":"sexCrimes","totalCrimes":24},{"crimeType":"other","totalCrimes":58}];
var width = 800,
height = 250,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(radius - 70);
var pie = d3.layout.pie()
.sort(null)
.value(function (d) {
return d.totalCrimes;
});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function (d) {
return color(d.data.crimeType);
});
g.append("text")
.attr("transform", function (d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("dy", ".35em")
.style("text-anchor", "middle")
.text(function (d) {
return d.data.crimeType;
});
This data updates frequenty so what would be the best way to update the pie? Look at this fiddle. Here I have another json called data2.
How could I simply replace data with data2 and have the pie animate/update?
Note: on some updates values could == 0
I have created a working version and have posted it here: http://www.ninjaPixel.io/StackOverflow/doughnutTransition.html (for some reason I couldn't get the transitions to play ball in fiddle, so have just posted it to my website instead).
To make the code clearer I have omitted your labelling, renamed 'data' to 'data1', and have stuck in some radio buttons to flip between the data arrays. The following snippet shows the important bits. You can get the whole code from my page above.
var svg = d3.select("#chartDiv").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("id", "pieChart")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var path = svg.selectAll("path")
.data(pie(data1))
.enter()
.append("path");
path.transition()
.duration(500)
.attr("fill", function(d, i) { return color(d.data.crimeType); })
.attr("d", arc)
.each(function(d) { this._current = d; }); // store the initial angles
function change(data){
path.data(pie(data));
path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
}
// Store the displayed angles in _current.
// Then, interpolate from _current to the new angles.
// During the transition, _current is updated in-place by d3.interpolate.
function arcTween(a) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function(t) {
return arc(i(t));
};
}
You may find this code of Mike Bostock's helpful, it is where I learned how to do this.
Here are some other similar questions that might help:
How to update pie chart using d3.js
d3 pie chart transition with attrtween
simple d3.js pie chart transitions *without* data joins?
Adding new segments to a Animated Pie Chart in D3.js
https://groups.google.com/forum/#!msg/d3-js/2o5NTVjVJgA/AslmRSxXUAgJ