D3 Charts Aligning the Titles and chart positions - javascript

I'm using D3 to draw a pie chart in my applicatio. I have created a pie chart with some sample data. But this chart is having alignment issues and adding a title didn't woked as expected,I added x, y attributes to place the chart but it didn't worked. I think I'm adding those to incorrect places.Can someone point out what's wrong here. Following is a sample code. My exact requirement is adding a title to the chart and getting the chart to center.
https://jsfiddle.net/yasirunilan/r8hkpx49/7/
var w = 400;
var h = 400;
var r = h/2;
var color = d3.scale.category20c();
var data = [{"label":"Category A", "value":20},
{"label":"Category B", "value":50},
{"label":"Category C", "value":30}];
var vis = d3.select('#container').append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")");
var pie = d3.layout.pie().value(function(d){return d.value;});
// declare an arc generator function
var arc = d3.svg.arc().outerRadius(r);
// select paths, use arc generator to draw
var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice");
arcs.append("svg:path")
.attr("fill", function(d, i){
return color(i);
})
.attr("d", function (d) {
// log the result of the arc generator to show how cool it is :)
console.log(arc(d));
return arc(d);
});
// add the text
arcs.append("svg:text").attr("transform", function(d){
d.innerRadius = 0;
d.outerRadius = r;
return "translate(" + arc.centroid(d) + ")";}).attr("text-anchor", "middle").text( function(d, i) {
return data[i].label;}
);

Related

showing data in tool tip of a PieChart

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);
});

D3JS graph donuts not showing some wedges when 2 donuts plotted

We are displaying donut pie chart using d3js in asp.net. We are using d3.json for passing json data to display wheel level1. Wheel level1 is display as per the data. We are using another d3.json for passing json data to display wheel level2. But starting wedges of wheel level2 are not display in pie chart.
I observed that if I plot the DoNut of Level1 and Level2 independently it shows all wedges of both Level 1, Level2 respectively.
When I changed the inner , out radius of Level1 and Level2 and displayed Level2 donut outside wiht Level1 donut inside, getting same problem of some wedges not displayed.
The data of angles is stored in MySQL database, using the same the graph is plotted. I checked the sum of angles of all wedges for the Level 2 is 360.
here is the graph
Sample code that is being used to plot Level1 DoNut
d3.json("http://localhost:50025/SportsWheelServices.asmx/WheelLevel1", function (error, data) {
data.forEach(function (d) {
d.SectionId = d.SectionId;
d.SectionLevel1 = d.SectionLevel1;
d.GroupName = d.GroupName;
d.SectionUpColor = d.SectionUpColor;
d.Rotation = d.Rotation;
});
var label = d3.arc()
.outerRadius(radius - 20)
.innerRadius(400);
var pie = d3.pie()
.sort(null)
.value(function (d) { return d.SectionLevel1; });
var arc = d3.arc()
.outerRadius(radius - 20)
.innerRadius(400);
var arcs = g.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
arcs.append("path")
.attr("d", arc)
.attr("fill", function (d, i) { return colors(data[i].SectionUpColor); });
arcs.append("text")
.attr("transform", function (d) {
var rotation = d.endAngle < Math.PI ? (d.startAngle / 2 + d.endAngle / 2) * 180 / Math.PI : (d.startAngle / 2 + d.endAngle / 2 + Math.PI) * 180 / Math.PI;
return "translate(" + label.centroid(d) + ") rotate("+ d.data.Rotation+") rotate(" + rotation + ")";
})
.attr("dy", "0.35em")
.text(function (d) { return d.data.GroupName; });
});
Code for Level2 DoNut
d3.json("http://localhost:50025/SportsWheelServices.asmx/WheelLevel2", function (error, data) {
data.forEach(function(d)
{
d.SectionId = d.SectionId;
d.SectionLevel2 = d.SectionLevel2;
});
var label = d3.arc()
.outerRadius(radius - 20)
.innerRadius(300);
var pie = d3.pie()
.sort(null)
.value(function (d) { return d.SectionLevel2; });
var arc = d3.arc()
.outerRadius(radius - 20)
.innerRadius(300);
var arcs = g.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
arcs.append("path")
.attr("d", arc)
.attr("fill", function (d, i) { return colors(i); });
});
instead of var arcs = g.selectAll(".arc") I added the following code var arcs = g.selectAll(".arc" + index) this solved my problem

Adding Legend on a basic chart

I am brand new to d3.js and stackoverflow so please pardon if I ask something very basic. I have a basic donut chart however it is a modification of a normal donut chart since you can see there is one on top of another. I was wondering if it is possible to add a label right on the chart. I am able to add legend and label outside the chart but i want to be able to add a label right on the chart itself.
This is the code for chart
var dataset = {
data1: [53245, 28479, 19697, 24037, 40245],
data2: [53245, 28479, 19697, 24037, 40245]
};
var width = 460,
height = 300,
cwidth = 45;
var color = d3.scale.category20();
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var gs = svg.selectAll("g").data(d3.values(dataset)).enter().append("g");
var path = gs.selectAll("path")
.data(function(d) { return pie(d); })
.enter().append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", function(d, i, j) { return arc.innerRadius(10+cwidth*j).outerRadius(cwidth*(j+1))(d); });
This is the FIDDLE. I would highly be pleased with any suggestions to be able to add label and legend. I would want label to be on top of both the charts in the fiddle.
Is this what you're looking for? Fiddle.
Essentially what this does is append a text element which is positioned using the angle of the path element.
var angle = d.endAngle - d.startAngle;
var loc = d.startAngle - (Math.PI/2) + (angle/2);
return Math.sin(loc) * radius;
If you want the labels on the left side to not overlap onto the chart you could use something similar to the following
var textLength = [];
gEnter.selectAll("text").each(function () {
textLength.push(this.getComputedTextLength());
});
To get the lengths of the text objects, then you can modify either .attr("x", ...) or .attr("transform", "translate(x,0)") when d.startAngle is greater than PI (meaning that it is on the left side of the chart), subtracting the text length from the x element to position it further left.

D3 Legend not updating

hoping you can help point out my mistake here...
I can't get the second row of the legend to update on mouseover of the histogram:
I don't believe it's the selector because you can add an id attribute to both no problem, and the data seems to be coming through ok on a console.log() ...little bit baffled.
http://jsfiddle.net/2sgLjbvu/3/
var data = [
{Supplier:"Supplier A",val: {WIP:"500",Conv:"400"}},
{Supplier:"Supplier B",val: {WIP:"1400",Conv:"400"}},
{Supplier:"Supplier C",val: {WIP:"300",Conv:"800"}},
{Supplier:"Supplier D",val: {WIP:"1000",Conv:"200"}}
];
dashboard("#chartArea",data);
function dashboard(id,fData){
var barColor='steelblue';
function segColor(c){return {WIP:"#807dba",Conv:"#41ab5d"}[c];}
//compute total for each supplier
fData.forEach(function (d){d.total = parseFloat(d.val.WIP) + parseFloat(d.val.Conv);});
//func to handle histogram
function histoGram(fD){
//Dimensions
var hG={}, hGDim = {t:60,r:0,b:30,l:0};
hGDim.w = 500 - hGDim.l - hGDim.r,
hGDim.h = 300 - hGDim.t - hGDim.b;
//create svg for histogram.
var hGsvg = d3.select(id).append("svg")
.attr("width",hGDim.w +hGDim.l + hGDim.r)
.attr("height",hGDim.h + hGDim.t + hGDim.b)
.append("g")
.attr("transform","translate(" + hGDim.l + "," + hGDim.t + ")");
//create function for x-axis mapping
var x = d3.scale.ordinal().rangeRoundBands([0,hGDim.w],0.1)
.domain(fD.map(function(d){return d[0];}));
//Add x-axis to histogram
hGsvg.append("g")
.attr("class","x axis")
.attr("transform","translate(0," + hGDim.h + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
//create function for y-axis mapping
var y = d3.scale.linear().range([hGDim.h,0])
.domain([0,d3.max(fD,function(d){
return d[1];
})]);
//create bars for the histogram to contain recs and val labels
var bars = hGsvg.selectAll(".bar")
.data(fD)
.enter()
.append("g")
.attr("class","bar");
//create the recs
bars.append("rect")
.attr("x",function(d){return x(d[0]);})
.attr("y",function(d){return y(d[1]);})
.attr("width",x.rangeBand())
.attr("height",function(d){return hGDim.h - y(d[1]);})
.attr("fill",barColor)
.on("mouseover",mouseover) //defined below
.on("mouseout",mouseout); //defined below
function mouseover(d){
//filter for selected supplier
var st = fData.filter(function(s){return s.Supplier==d[0];})[0],
nD = d3.keys(st.val).map(function(s){return {type:s,val:st.val[s]};});
pC.update(nD);
leg.update(nD);
}
function mouseout(d){
//reset the pie-chart and legend
pC.update(tF);
leg.update(tF);
}
//func to update the bars - this will be used by the pie-chart
hG.update = function(nD,color){
//update domain of the y-axis to reflect change in supp
y.domain([0,d3.max(nD,function(d){return d[1];})]);
//attach the new data to the bars
var bars = hGsvg.selectAll(".bar")
.data(nD);
//transition of the height and color of rectangles
bars.select("rect")
.transition()
.duration(500)
.attr("y",function(d){return y(d[1]);})
.attr("height",function(d){return hGDim.h - y(d[1]);})
.attr("fill",color);
//transition the frequency labels loc
bars.select("text")
.transition()
.duration(500)
.text(function(d){ return d3.format(",")(d[1]);})
.attr("y",function(d){return y(d[1])-5;});
};
return hG;
}
function pieChart(pD){
var pC={},pieDim={w:250,h:250};
pieDim.r = Math.min(pieDim.w,pieDim.h)/2;
//create svg for pie chart
var piesvg = d3.select(id).append("svg")
.attr("width",pieDim.w)
.attr("height",pieDim.h)
.append("g")
.attr("transform","translate(" + pieDim.w/2 + "," + pieDim.h/2 + ")");
//create func to draw arcs of the slices
var arc = d3.svg.arc()
.outerRadius(pieDim.r-10)
.innerRadius(0);
var pie = d3.layout.pie()
.sort(null)
.value(function(d){return d.val;});
//Draw the pie slices
piesvg.selectAll("path")
.data(pie(pD))
.enter()
.append("path")
.attr("d",arc)
.each(function(d){this._current=d;})
.style("fill",function(d){return segColor(d.data.type);})
.on("mouseover",mouseover)
.on("mouseout",mouseout);
//create func to update pie-chart, this will be used by the histogram
pC.update = function(nD){
piesvg.selectAll("path")
.data(pie(nD))
.transition()
.duration(500)
.attrTween("d",arcTween);
};
//Utility func to be called on mouseover a pie slice
function mouseover(d){
//call the update function of the histogram with new data
hG.update(fData.map(function(v){
return[v.Supplier,v.val[d.data.type]];}),segColor(d.data.type));
}
//Utility func to be called on mouseout of a pie slice
function mouseout(d){
//call the update func of histogram with all data
hG.update(fData.map(function(v){
return[v.Supplier,v.total];}),barColor);
}
//Animate the pie-slice requiring a custom function which specifies
//how the intermeidate paths should be draw
function arcTween(a){
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function(t){return arc(i(t));};
}
return pC;
}
//func to handle legend
function legend(lD){
leg={};
//create table for legend
var lgend = d3.select(id)
.append("table")
.attr("class","legend");
//create one row per segment
var tr = lgend.append("tbody")
.selectAll("tr")
.data(lD)
.enter()
.append("tr");
//create the first column for each segment
tr.append("td")
.append("svg")
.attr("width","16")
.attr("height","16")
.append("rect")
.attr("width","16")
.attr("height","16")
.attr("fill",function(d){return segColor(d.type);});
//create the second column for each segment
tr.append("td")
.text(function(d){return d.type;});
//create the third col
tr.append("td")
.attr("class","legendFreq")
.text(function(d){return d3.format(",")(d.val);});
//create the perc col
tr.append("tr")
.attr("class","legendPerc")
.text(function(d){return getLegend(d,lD);});
//utility func to be used to update the legend
leg.update = function(nD){
var l = lgend.select("tbody")
.selectAll("tr")
.data(nD);
l.select(".legendFreq")
.text(function(d){return d3.format(",")(d.val);});
l.select(".legendPerc")
.text(function(d){return getLegend(d,nD);});
};
function getLegend(d,aD){//utility func to compute perc
return d3.format("%")(d.val/d3.sum(aD.map(function(v){return v.val;})));
}
return leg;
}
var sF = fData.map(function(d){
return [d.Supplier,d.total];
});
var tF = ['WIP','Conv'].map(function(d){
return {type:d,val:d3.sum(fData.map(function(t){return t.val[d];}))};
});
var hG = histoGram(sF),
pC=pieChart(tF),
leg = legend(tF);
}
Got it...
//create the perc col
tr.append("tr")
.attr("class","legendPerc")
.text(function(d){return getLegend(d,lD);});
should have been...
//create the perc col
tr.append("td")
.attr("class","legendPerc")
.text(function(d){return getLegend(d,lD);});

Adding clock points to d3 pie chart

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.

Categories