I am new to D3 charts
i am using D3 dashboard chart following link
http://bl.ocks.org/diethardsteiner/3287802
here the datas are given by variables.
I don't want to get the value from variable and i want to get the value from json file.
Before the data are stored in a variable.
################ FORMATS ##################
-------------------------------------------
*/
var formatAsPercentage = d3.format("%"),
formatAsPercentage1Dec = d3.format(".1%"),
formatAsInteger = d3.format(","),
fsec = d3.time.format("%S s"),
fmin = d3.time.format("%M m"),
fhou = d3.time.format("%H h"),
fwee = d3.time.format("%a"),
fdat = d3.time.format("%d d"),
fmon = d3.time.format("%b")
;
/*
############# PIE CHART ###################
-------------------------------------------
*/
function dsPieChart(){
var dataset = [
{category: "ACC", measure: 0.30},
{category: "B56", measure: 0.25},
{category: "MAB", measure: 0.15},
]
;
var width = 400,
height = 400,
outerRadius = Math.min(width, height) / 2,
innerRadius = outerRadius * .999,
innerRadiusFinal = outerRadius * .5,
innerRadiusFinal3 = outerRadius* .45,
color = d3.scale.category20()
;
var vis = d3.select("#pieChart")
.append("svg:svg")
.data([dataset])
.attr("width", width)
.attr("height", height)
.append("svg:g")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")")
;
var arc = d3.svg.arc()
.outerRadius(outerRadius).innerRadius(innerRadius);
var arcFinal = d3.svg.arc().innerRadius(innerRadiusFinal).outerRadius(outerRadius);
var arcFinal3 = d3.svg.arc().innerRadius(innerRadiusFinal3).outerRadius(outerRadius);
var pie = d3.layout.pie()
.value(function(d) { return d.measure; });
var arcs = vis.selectAll("g.slice")
.data(pie)
.enter()
.append("svg:g")
.attr("class", "slice")
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.on("click", up)
;
arcs.append("svg:path")
.attr("fill", function(d, i) { return color(i); } )
.attr("d", arc)
.append("svg:title")
.text(function(d) { return d.data.category + ": " + formatAsPercentage(d.data.measure); });
d3.selectAll("g.slice").selectAll("path").transition()
.duration(750)
.delay(10)
.attr("d", arcFinal )
;
arcs.filter(function(d) { return d.endAngle - d.startAngle > .2; })
.append("svg:text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.attr("transform", function(d) { return "translate(" + arcFinal.centroid(d) + ")rotate(" + angle(d) + ")"; })
.text(function(d) { return d.data.category; })
;
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
// Pie chart title
vis.append("svg:text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text("Building")
.attr("class","title")
;
function mouseover() {
d3.select(this).select("path").transition()
.duration(750)
.attr("d", arcFinal3)
;
}
function mouseout() {
d3.select(this).select("path").transition()
.duration(750)
.attr("d", arcFinal)
;
}
function up(d, i) {
updateBarChart(d.data.category, color(i));
updateLineChart(d.data.category, color(i));
}
}
dsPieChart();
now i am trying to get the data by folowing way.
I dont know this is correct way or not can anyone help me
################ FORMATS ##################
-------------------------------------------
*/
var formatAsPercentage = d3.format("%"),
formatAsPercentage1Dec = d3.format(".1%"),
formatAsInteger = d3.format(","),
fsec = d3.time.format("%S s"),
fmin = d3.time.format("%M m"),
fhou = d3.time.format("%H h"),
fwee = d3.time.format("%a"),
fdat = d3.time.format("%d d"),
fmon = d3.time.format("%b")
;
/*
############# PIE CHART ###################
-------------------------------------------
*/
function dsPieChart(){
var width = 400,
height = 400,
outerRadius = Math.min(width, height) / 2,
innerRadius = outerRadius * .999,
// for animation
innerRadiusFinal = outerRadius * .5,
innerRadiusFinal3 = outerRadius* .45,
color = d3.scale.category20() //builtin range of colors
;
});
var vis = d3.select("#pieChart")
.append("svg")
d3.json("readme.json", function(error, root) {
if (error) throw error;
.data([root])
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")")
})
;
var arc = d3.svg.arc()
.outerRadius(outerRadius).innerRadius(innerRadius);
var arcFinal = d3.svg.arc().innerRadius(innerRadiusFinal).outerRadius(outerRadius);
var arcFinal3 = d3.svg.arc().innerRadius(innerRadiusFinal3).outerRadius(outerRadius);
var pie = d3.layout.pie()
.value(function(d) { return d.measure; });
var arcs = vis.selectAll("g.slice")
.data(pie)
.enter()
.append("g")
.attr("class", "slice")
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.on("click", up)
;
arcs.append("path")
.attr("fill", function(d, i) { return color(i); } )
.attr("d", arc)
.append("title")
.text(function(d) { return d.data.category + ": " + formatAsPercentage(d.data.measure); });
d3.selectAll("g.slice").selectAll("path").transition()
.duration(750)
.delay(10)
.attr("d", arcFinal )
;
arcs.filter(function(d) { return d.endAngle - d.startAngle > .2; })
.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.attr("transform", function(d) { return "translate(" + arcFinal.centroid(d) + ")rotate(" + angle(d) + ")"; })
.text(function(d) { return d.data.category; })
;
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
vis.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text("Building")
.attr("class","title")
;
function mouseover() {
d3.select(this).select("path").transition()
.duration(750)
.attr("d", arcFinal3)
;
}
function mouseout() {
d3.select(this).select("path").transition()
.duration(750)
.attr("d", arcFinal)
;
}
function up(d, i) {
updateBarChart(d.data.category, color(i));
updateLineChart(d.data.category, color(i));
}
}
dsPieChart();
can any one give a correct solution
Thanks,
Vinoth
Just create a JSON file with this structure:
[{
"category": "ACC",
"measure": 0.30
}, {
"category": "B56",
"measure": 0.25
}, {
"category": "MAB",
"measure": 0.15
}]
And use d3.json:
d3.json("data.json", function(dataset){
//code here
});
Here is a plunker showing it: https://plnkr.co/edit/OUjPNY3W2aXXCSxvm4tZ?p=preview
Related
I'm trying to create a set of text elements and place them above various rect elements so that it looks as if they were inside. the thing is that I haven't been able to accomplish this simple task.
The text elements I need inside the column of rect's are the elements of the array: var dataDnt4 = [42,31,16,4,3,2,1];
I'll leave a running snippet so that you can my progress so far.
Your help is very appreciated. thanks
var icon2 = '<g><path class="st0" d="M23.1,34.9c6.9,0,12.5-5.6,12.5-12.5c0-6.9-5.6-12.5-12.5-12.5c-6.9,0-12.5,5.6-12.5,12.5 C10.6,29.3,16.2,34.9,23.1,34.9L23.1,34.9z"/><path class="st0" d="M39.2,54.6c0.2,0,0.4,0,0.7,0c-3.7-3-6-7.5-6-12.6c0-1.2,0.1-2.4,0.4-3.6c-0.1,0-0.3,0-0.4,0H12.4 C5.5,38.5-0.1,44.1-0.1,51v17.9h23.3C24.1,60.8,30.9,54.6,39.2,54.6L39.2,54.6z"/><path class="st0" d="M76.8,34.9c6.9,0,12.5-5.6,12.5-12.5c0-6.9-5.6-12.5-12.5-12.5c-6.9,0-12.5,5.6-12.5,12.5 C64.2,29.3,69.9,34.9,76.8,34.9L76.8,34.9z"/><path class="st0" d="M87.5,38.5H66c-0.1,0-0.3,0-0.4,0c0.3,1.1,0.4,2.3,0.4,3.6c0,5.1-2.4,9.6-6,12.6c0.2,0,0.4,0,0.7,0 c8.3,0,15.1,6.3,16,14.3H100V51C100,44.1,94.4,38.5,87.5,38.5L87.5,38.5z"/><path class="st0" d="M49.9,54.6c6.9,0,12.5-5.6,12.5-12.5c0-6.9-5.6-12.5-12.5-12.5c-6.9,0-12.5,5.6-12.5,12.5 C37.4,49,43,54.6,49.9,54.6L49.9,54.6z"/><path class="st0" d="M60.7,58.1H39.2c-6.9,0-12.5,5.6-12.5,12.5v17.9h46.5V70.7C73.2,63.7,67.6,58.1,60.7,58.1L60.7,58.1z"/></g>'
var dataDnt4 = [42, 31, 16, 4, 3, 2, 1];
var distanciaRect = [25, 50, 75, 100, 125, 150, 175]
var width = 512,
height = 600
radius = (Math.min(width, height) / 2.5) - 60;
var sym = "%"
var legendTextArr = ["alpha", "beta", "Gamma", "vvv", "www", "xxx", "yyy", "zzz"]
var color_rect = ["#00338D", "#BC204B", "#0091DA", "#eaaa00", "#005eb8", "#f68d2e", "#009444", "#470a68"]
var pie = d3.pie()
.value(function(d) {
return d
})(dataDnt4);
var arc = d3.arc()
.outerRadius(radius - 10)
.innerRadius(radius - (radius / 2.4));
var labelArc = d3.arc()
.outerRadius(radius - 35)
.innerRadius(radius - 35);
var svg = d3.select("#chartdiv")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2.4 + ")");
var title = svg.append("text")
.attr("font-weight", "bold")
.attr("class", "title1")
.html("title 1")
.attr("transform", function() {
return "translate(" + (-184) + "," + (-180) + ")"
})
var title = svg.append("text")
.attr("font-weight", "bold")
.attr("class", "title2")
.html("title 2")
.attr("transform", function() {
return "translate(" + (-184) + "," + (-160) + ")"
})
var legendG = svg.append("g")
.attr("class", "legendG")
.attr("transform", function() {
return "translate(" + (-60) + "," + (155) + ")"
})
var legendG = svg.append("g")
.attr("class", "legendG")
.attr("transform", function() {
return "translate(" + (-60) + "," + (155) + ")"
})
var legendText = legendG.selectAll("text")
.data(distanciaRect)
.enter()
.append("text")
.attr("x", -80)
.attr("y", function(d, i) {
return d + 10
})
.data(legendTextArr)
.html(function(d) {
return d
})
var legends = legendG.selectAll(".rect")
.data(distanciaRect)
.enter()
.append("rect")
.attr("x", -120)
.attr("y", function(d, i) {
return d
})
.attr("width", 25)
.attr("height", 17)
.attr("class", "icon1")
.data(color_rect)
.attr("fill", function(d, i) {
return d
})
var g = svg.selectAll("arc")
.data(pie)
.enter().append("g")
.attr("class", "arc");
function easeInverse(ease) {
return function(e) {
var min = 0,
max = 1;
while (max - min > 1e-3) {
var mid = (max + min) * 0.5;
emid = ease(mid);
if (emid > e) {
max = mid;
} else {
min = mid;
}
}
return max;
}
}
var inverseCubic = easeInverse(d3.easeCubic);
var oneOver2Pi = 1.0 / (2 * Math.PI);
var total_msec = 2000;
g.append("path")
.attr("d", arc)
.attr("transform", function() {
return "translate(" + (-16) + "," + (0) + ")"
})
.style("fill", function(d, i) {
return color_rect[i];
})
.transition()
.ease(d3.easeLinear)
.delay(function(d) {
return total_msec * inverseCubic(d.startAngle * oneOver2Pi);
})
.duration(function(d) {
return total_msec * (inverseCubic(d.endAngle * oneOver2Pi) - inverseCubic(d.startAngle * oneOver2Pi));
})
.attrTween("d", arcTween);
function arcTween(d) {
var i = d3.interpolate(inverseCubic(d.startAngle * oneOver2Pi), inverseCubic(d.endAngle * oneOver2Pi));
return function(t) {
d.endAngle = 2 * Math.PI * d3.easeCubic(i(t));
return arc(d);
}
}
svg.append("g")
.attr("class", "icon2")
.html(icon2);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="chartdiv"></div>
There are numerous ways to do this, so here is one possible way. I would group together the three pieces of the legend--the rectangle, the key text, and the text over the rectangle--in a g element and bind dataDnt4 to each item. The rectangle colour and the legend text can be retrieved by position, i.e. the first dataDnt4 item corresponds to color_rect[0] and legendTextArr[0], the second to color_rect[1] and legendTextArr[1], etc.
I've cut out the code that is not relevant to the positioning of the legend items -- you can restore that in your script.
var width = 512,
height = 600,
radius = (Math.min(width, height) / 2.5) - 60;
var sym = "%"
var legendTextArr = ["alpha", "beta", "Gamma", "vvv", "www", "xxx", "yyy", "zzz"]
var dataDnt4 = [42, 31, 16, 4, 3, 2, 1];
var color_rect = ["#00338D", "#BC204B", "#0091DA", "#eaaa00", "#005eb8", "#f68d2e", "#009444", "#470a68"]
var svg = d3.select("#chartdiv")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2.4 + ")");
var title = svg.append("text")
.attr("font-weight", "bold")
.attr("class", "title1")
.html("scroll down!")
.attr("transform", function() {
return "translate(" + -184 + "," + -180 + ")"
})
var legendG = svg.append("g")
.attr("class", "legendG")
.attr("transform", function() {
// this moves the whole legend box
// you can change this to whatever transformation is appropriate for your chart
return "translate(" + -((width / 2)-40) + "," + 120 + ")"
})
// group each legend item in a `g` element
var legendText = legendG.selectAll("g")
.data(dataDnt4)
.enter()
.append('g')
.attr('transform', function(d, i) {
// instead of having a hard-coded list of multiples of 25, you can multiply
// the array index, `i`, by 25 to get the correct position
return 'translate(0,' + (i*25) + ')';
});
legendText.append("rect")
.attr("width", 25)
.attr("height", 17)
.attr("class", "icon1")
.attr("fill", function(d, i) {
return color_rect[i];
})
// the text "in" the rectangle
// use 'text-anchor: middle' and an x offset of 12.5 (rectangle width / 2)
// to centre the labels
// change the `y` attribute to alter the vertical positioning
legendText.append("text")
.attr("x", 12.5)
.attr("y", 13)
.attr('text-anchor', 'middle')
.attr('fill', 'white')
// d is the items in dataDnt4
.text(function(d) {
return d;
})
// legend text items
legendText.append("text")
.attr("x", 40)
.attr("y", 13)
// take legendTextArr item in position i
.text(function(d,i) {
return legendTextArr[i];
})
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="chartdiv"></div>
You have some errors in your code (e.g. you declare the variables legendG and title twice), and it would probably be helpful for you to run your code through a code linter so you can see the problems that you might not pick up by eye.
I have a project that almost works the way I want. When a smaller dataset is added, slices are removed. It fails when a larger dataset is added. The space for the arc is added but no label or color is added for it.
This is my enter() code:
newArcs.enter()
.append("path")
.attr("stroke", "white")
.attr("stroke-width", 0.8)
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
What am I doing wrong?
I've fixed the code such that it works now:
// Tween Function
var arcTween = function(a) {
var i = d3.interpolate(this.current || {}, a);
this.current = i(0);
return function(t) {
return arc(i(t));
};
};
// Setup all the constants
var duration = 500;
var width = 500
var height = 300
var radius = Math.floor(Math.min(width / 2, height / 2) * 0.9);
var colors = ["#d62728", "#ff9900", "#004963", "#3497D3"];
// Test Data
var d2 = [{
label: 'apples',
value: 20
}, {
label: 'oranges',
value: 50
}, {
label: 'pears',
value: 100
}];
var d1 = [{
label: 'apples',
value: 100
}, {
label: 'oranges',
value: 20
}, {
label: 'pears',
value: 20
}, {
label: 'grapes',
value: 20
}];
// Set the initial data
var data = d1
var updateChart = function(dataset) {
arcs = arcs.data(donut(dataset), function(d) { return d.data.label });
arcs.exit().remove();
arcs.enter()
.append("path")
.attr("stroke", "white")
.attr("stroke-width", 0.8)
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
arcs.transition()
.duration(duration)
.attrTween("d", arcTween);
sliceLabel = sliceLabel.data(donut(dataset), function(d) { return d.data.label });
sliceLabel.exit().remove();
sliceLabel.enter()
.append("text")
.attr("class", "arcLabel")
.attr("transform", function(d) {
return "translate(" + (arc.centroid(d)) + ")";
})
.attr("text-anchor", "middle")
.style("fill-opacity", function(d) {
if (d.value === 0) {
return 1e-6;
} else {
return 1;
}
})
.text(function(d) {
return d.data.label;
});
sliceLabel.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + (arc.centroid(d)) + ")";
})
.style("fill-opacity", function(d) {
if (d.value === 0) {
return 1e-6;
} else {
return 1;
}
});
};
var color = d3.scale.category20();
var donut = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.svg.arc()
.innerRadius(radius * .4)
.outerRadius(radius);
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var arc_grp = svg.append("g")
.attr("class", "arcGrp")
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
var label_group = svg.append("g")
.attr("class", "lblGroup")
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
var arcs = arc_grp.selectAll("path");
var sliceLabel = label_group.selectAll("text");
updateChart(data);
// returns random integer between min and max number
function getRand() {
var min = 1,
max = 2;
var res = Math.floor(Math.random() * (max - min + 1) + min);
//console.log(res);
return res;
}
// Update the data
setInterval(function(model) {
var r = getRand();
return updateChart(r == 1 ? d1 : d2);
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
I have prototype code I am working with here:
jsfiddle
The example shows how to add a segment when new data is added but not how to remove it again when the data changes [back]. I am fairly new to d3 and don't quite get the exit() function yet...
if you reverse the initial and second dataset you will see that the grapes segment is never removed. Thanks in advance!
any help would be great!
The update code: (my final chart needs to update on a timer when data changes)
var arcs = arc_grp.selectAll("path")
.data(donut(data));
arcs.enter()
.append("path")
.attr("stroke", "white")
.attr("stroke-width", 0.8)
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.each(function(d) { return this.current = d; });
var sliceLabel = label_group.selectAll("text")
.data(donut(data));
sliceLabel.enter()
.append("text")
.attr("class", "arcLabel")
.attr("transform", function(d) { return "translate(" + (arc.centroid(d)) +
")"; })
.attr("text-anchor", "middle")
.style("fill-opacity", function(d) {
if (d.value === 0) { return 1e-6; }
else { return 1; }
})
.text(function(d) { return d.data.label; });
};
To remove elements without data, you have to use exit(), which...
Returns the exit selection: existing DOM elements in the selection for which no new datum was found.
So, inside your updateChart function, you need an exit selection for both paths and texts:
var newArcs = arcs.data(donut(dataset));
newArcs.exit().remove();
var newSlices = sliceLabel.data(donut(dataset));
newSlices.exit().remove();
Here is your updated code:
// Setup all the constants
var duration = 500;
var width = 500
var height = 300
var radius = Math.floor(Math.min(width / 2, height / 2) * 0.9);
var colors = ["#d62728", "#ff9900", "#004963", "#3497D3"];
// Test Data
var d2 = [{
label: 'apples',
value: 20
}, {
label: 'oranges',
value: 50
}, {
label: 'pears',
value: 100
}];
var d1 = [{
label: 'apples',
value: 100
}, {
label: 'oranges',
value: 20
}, {
label: 'pears',
value: 20
}, {
label: 'grapes',
value: 20
}];
// Set the initial data
var data = d1
var updateChart = function(dataset) {
var newArcs = arcs.data(donut(dataset));
newArcs.exit().remove();
newArcs.enter()
.append("path")
.attr("stroke", "white")
.attr("stroke-width", 0.8)
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
newArcs.transition()
.duration(duration)
.attrTween("d", arcTween);
var newSlices = sliceLabel.data(donut(dataset));
newSlices.exit().remove();
newSlices.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + (arc.centroid(d)) + ")";
})
.style("fill-opacity", function(d) {
if (d.value === 0) {
return 1e-6;
} else {
return 1;
}
});
sliceLabel.data(donut(dataset)).enter()
.append("text")
.attr("class", "arcLabel")
.attr("transform", function(d) {
return "translate(" + (arc.centroid(d)) + ")";
})
.attr("text-anchor", "middle")
.style("fill-opacity", function(d) {
if (d.value === 0) {
return 1e-6;
} else {
return 1;
}
})
.text(function(d) {
return d.data.label;
});
};
var color = d3.scale.category20();
var donut = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.svg.arc()
.innerRadius(radius * .4)
.outerRadius(radius);
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var arc_grp = svg.append("g")
.attr("class", "arcGrp")
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
var label_group = svg.append("g")
.attr("class", "lblGroup")
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
var arcs = arc_grp.selectAll("path")
.data(donut(data));
arcs.enter()
.append("path")
.attr("stroke", "white")
.attr("stroke-width", 0.8)
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc)
.each(function(d) {
return this.current = d;
});
var sliceLabel = label_group.selectAll("text")
.data(donut(data));
sliceLabel.enter()
.append("text")
.attr("class", "arcLabel")
.attr("transform", function(d) {
return "translate(" + (arc.centroid(d)) + ")";
})
.attr("text-anchor", "middle")
.style("fill-opacity", function(d) {
if (d.value === 0) {
return 1e-6;
} else {
return 1;
}
})
.text(function(d) {
return d.data.label;
});
// Update the data
setInterval(function(model) {
return updateChart(d2);
}, 2000);
// Tween Function
var arcTween = function(a) {
var i = d3.interpolate(this.current, a);
this.current = i(0);
return function(t) {
return arc(i(t));
};
};
.arcLabel {
font: 10px sans-serif;
fill: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
In Normalized stacked bar I am trying to bind data in all rect in a bar but wrong value is passed. I adopted my code from this example and made it horizontal. Below is my code and I have created a plunker as well. In .text function entire object is passed. Can someone help me where I am going wrong
var svg = d3.select("svg"),
margin = {
top: 20,
right: 60,
bottom: 30,
left: 40
},
/*width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,*/
width = 120,
height = 120,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var y = d3.scaleBand()
.rangeRound([0, width])
.padding(0.1)
.align(0.1);
var x = d3.scaleLinear()
.rangeRound([height, 0]);
var z = d3.scaleOrdinal()
.range(['#02CA22', '#FB5652', '#FFB005']);
var stack = d3.stack()
.offset(d3.stackOffsetExpand);
d3.csv("data.csv", type, function (error, data) {
if (error) throw error;
/*data.sort(function(a, b) {
return b[data.columns[1]] / b.total - a[data.columns[1]] / a.total;
});*/
y.domain(data.map(function (d) {
return d.State;
}));
z.domain(data.columns.slice(1));
var serie = g.selectAll(".serie")
.data(stack.keys(data.columns.slice(1))(data))
.enter().append("g")
.attr("class", "serie")
.attr("fill", function (d) {
return z(d.key);
});
var rect = serie.selectAll("rect")
.data(function (d) {
return d;
}).enter();
rect.append("rect")
.attr("y", function (d) {
return y(d.data.State);
})
.attr("x", function (d) {
return x(d[1]);
})
.attr("width", function (d) {
return x(d[0]) - x(d[1]);
})
.attr("height", y.bandwidth());
rect.append("text")
.text(function (d) {
console.log('d');
console.log(d);
console.log(d.data.key);
return 'val';
})
.attr("y", function (d) { return y(d.data.State) + y.bandwidth() / 2; })
.attr("x", function (d) {
return x(d[1]);
});
/* g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(2, "%"));*/
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y));
var legend = serie.append("g")
.attr("class", "legend")
.attr("transform", function (d) {
var d = d[0];
return "translate(" + ((x(d[0]) + x(d[1])) / 2) + ", " + (y(d.data.State) - y.bandwidth()) + ")";
});
/*legend.append("line")
.attr("y1", 5)
.attr("x1", 15)
.attr("x2", 15)
.attr("y2", 12)
.attr("stroke", "#000");
legend.append("text")
.attr("x", 9)
.attr("dy", "0.35em")
.attr("fill", "#000")
.style("font", "10px sans-serif")
.text(function (d) {
return d.key;
}); */
});
function type(d, i, columns) {
var t;
for (i = 1, t = 0; i < columns.length; ++i) t += d[columns[i]] = +d[columns[i]];
d.total = t;
return d;
}
I think the best way to do this is to modify your subselection data-binding to include that information:
var rect = serie.selectAll("rect")
.data(function (d) {
// return all the data you need as flat as possible
var rv = d.map(function(da){
return {p: da, key: d.key, state: da.data.State}
});
return rv;
}).enter();
The text is then available as:
rect.append("text")
.text(function (d) {
return d.key;
})
.attr("y", function (d) { return y(d.state) + y.bandwidth() / 2; })
.attr("x", function (d) {
return x(d.p[1]);
});
Updated Plunker.
I am drawing a pie chart and in each arc i write the text in the centre. However when the arc is too small, the text gets misaligned. How do i restrict writing the text if the arc is too thin. Is there a way to identify the arc and not write the text.
My code:
var arc = d3.svg.arc()
.outerRadius(radius - 45)
.innerRadius(radius -200);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {return d.Components;});
var g = svg.selectAll(".arc")
.data(pie(newdata))
.enter().append("g")
.attr("class", "arc")
.attr("id", function(d,i) {return "group" + i})
g.append("path")
.attr("d", arc)
.style("fill","#FFFFFF")
.transition()
.ease("bounce")
.duration(1000)
.delay(function(d, i) {return i * 500;})
.style("fill", function(d,i)
{
var c = d.data.Source;
if (c=="GREEN")
{
return "#78a22f";
}
else if (c=="RED")
{
return "#a00000";
}
else if (c=="AMBER")
{
return "#Ffb400";
}
else
{
return "#DADCF6";
}
});
g.append("text")
.attr("transform", function(d)
{
//comment
var c = arc.centroid(d);
var param,param1
param = c[1]- 20;
param1= c[0]- 38;
return "translate(" + param1 + "," + param + ")";
})
.attr("dy", ".35em")
.style("text-anchor", "middle")
.attr("style","font-family: Arial;border: solid 1px" )
.transition()
.ease("bounce")
.duration(1000)
.delay(function(d, i) {return i * 500;})
.text(function(d) {
return ((d.data.Status));
}
});
g.append("text")
.attr("transform", function(d)
{
var c = arc.centroid(d);
var param = c[1];
var param1=c[0];
return "translate(" + param1 + "," + param + ")";
})
.attr("dy", ".35em")
.style("text-anchor", "middle")
.transition()
.ease("bounce")
.duration(1000)
.delay(function(d, i) {return i * 500;})
.text(function(d) {
if (eval(d.data.Components) >0)
{
return (Number(d.data.Components).toFixed(0)) + " (" + (Number(d.data.Percentage).toFixed(1) + "%)");
}
});
data is like:
"Source","Components","Percentage","Business Unit","Status","BUId"
"RED","20","4.77","Financial & Risk - ALL","Analyzed","67001003"
"AMBER","2","0.48","Financial & Risk - ALL","Identified","67001003"
"GREEN","21","5.01","Financial & Risk - ALL","Approved","67001003"
"PALEBLUE","83","19.81","Financial & Risk - ALL","Unmapped","67001003"
"GREY","293","69.93","Financial & Risk - ALL","Not Applicable","67001003"