My problem is labels of donut chart too long. It'll be cut lost when it get over width or height of svg.
i don't know how i must cut it to 2 or more line. I try to add tag div outside tag text but it's wrong. Who can give me a solution. This is my code:
var tooltip = d3.select('#chart')
.append('div')
.attr('class', 'tooltips');
tooltip.append('div')
.attr('class', 'label');
var data = [
{country: "UNITED KINGDOMhhhhhhhhhhhhhhhhhhhhhhhhh hhhhhhhhhhhhhhhhh", val: 86.68},
{country: "HONG KONGggggggggggggggggggggg g g g gg g g g g gg gg g g ", val: 9.23},
{country: "OTHERS", val: 4.09}
];
var w = 600,
h = 600,
r = Math.min(w, h) / 2 - 100,
labelr = r + 30, // radius for label anchor
color = d3.scale.category20(),
donut = d3.layout.pie(),
arc = d3.svg.arc().innerRadius(r * .6).outerRadius(r);
var vis = d3.select("#chart")
.append("svg:svg")
.data([data])
.attr("width", w + 150)
.attr("height", h);
var arcs = vis.selectAll("g.arc")
.data(donut.value(function(d) { return d.val }))
.enter().append("svg:g")
.attr("class", "arc")
.attr("transform", "translate(" + (r + 200) + "," + (r+100) + ")");
var arcOver = d3.svg.arc()
.innerRadius(r * .57)
.outerRadius(r + 5);
arcs.append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.on("mouseover",function(d){
d3.select(this).transition()
.duration(50)
.attr("d", arcOver);
tooltip.select('.label').html(d.value + "%");
tooltip.style('display', 'block');
})
.on('mouseout', function() {
d3.select(this).transition()
.duration(50)
.attr("d", arc);
tooltip.style('display', 'none');
})
.on('mousemove', function(d) {
tooltip.style('top', (d3.event.pageY - 80) + 'px')
.style('left', (d3.event.pageX + 10) + 'px');
});
arcs.append("text")
.attr("transform", function(d) {
var c = arc.centroid(d),
x = c[0],
y = c[1],
// pythagorean theorem for hypotenuse
h = Math.sqrt(x*x + y*y);
return "translate(" + (x/h * labelr) + ',' +
(y/h * labelr) + ")";
})
.attr("dy", ".35em")
.attr("text-anchor", function(d) {
// are we past the center?
return (d.endAngle + d.startAngle)/2 > Math.PI ?
"end" : "start";
})
.text(function(d) { return d.data.country; });
Thanks!!!
var tooltip = d3.select('#chart')
.append('div')
.attr('class', 'tooltips');
tooltip.append('div')
.attr('class', 'label');
var data = [
{country: "UNITED KINGDOMhhhhhhhhhhhhhhhhhhhhhhhhh hhhhhhhhhhhhhhhhh", val: 86.68},
{country: "HONG KONGggggggggggggggggggggg g g g gg g g g g gg gg g g ", val: 9.23},
{country: "OTHERS", val: 4.09}
];
var w = 600,
h = 600,
r = Math.min(w, h) / 2 - 100,
labelr = r + 30, // radius for label anchor
color = d3.scale.category20(),
donut = d3.layout.pie(),
arc = d3.svg.arc().innerRadius(r * .6).outerRadius(r);
var vis = d3.select("#chart")
.append("svg:svg")
.data([data])
.attr("width", w + 150)
.attr("height", h);
var arcs = vis.selectAll("g.arc")
.data(donut.value(function(d) { return d.val }))
.enter().append("svg:g")
.attr("class", "arc")
.attr("transform", "translate(" + (r + 200) + "," + (r+100) + ")");
var arcOver = d3.svg.arc()
.innerRadius(r * .57)
.outerRadius(r + 5);
arcs.append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.on("mouseover",function(d){
d3.select(this).transition()
.duration(50)
.attr("d", arcOver);
tooltip.select('.label').html(d.value + "%");
tooltip.style('display', 'block');
})
.on('mouseout', function() {
d3.select(this).transition()
.duration(50)
.attr("d", arc);
tooltip.style('display', 'none');
})
.on('mousemove', function(d) {
tooltip.style('top', (d3.event.pageY - 80) + 'px')
.style('left', (d3.event.pageX + 10) + 'px');
});
var text = arcs.append("text")
.attr("transform", function(d) {
var c = arc.centroid(d),
x = c[0],
y = c[1],
// pythagorean theorem for hypotenuse
h = Math.sqrt(x*x + y*y);
return "translate(" + (x/h * labelr) + ',' +
(y/h * labelr) + ")";
})
.attr("dy", ".35em")
.attr("text-anchor", function(d) {
// are we past the center?
return (d.endAngle + d.startAngle)/2 > Math.PI ?
"end" : "start";
});/*
.text(function(d) {
return d.data.country;
});*/
text.each(function(d){
var text = d3.select(this),
words = d.data.country.split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 0.22, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null)
.append("tspan")
.attr("x", 0)
.attr("y", y)
.attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > 10) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan")
.attr("x", 0)
.attr("y", y)
.attr("dy", ++lineNumber * lineHeight + dy + "em")
.text(word);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id='chart'></div>
After doing a great lot of work out. I got this.
Hope this will fulfill your need/requirement.
All I did is,
Adding tspan elements to text element.Observe below code. text is a var see above code. which holds all text elements which we want to add to the every g
text.each(function(d){
var text = d3.select(this),//selecting current text element
words = d.data.country.split(/\s+/).reverse(),//splitting the country name by using space, if you want you can change.
word,//to store one one word
line = [],
lineNumber = 0,
lineHeight = 0.22, // ems, you can increase for more gaps vise versa
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null)
.append("tspan")
.attr("x", 0)
.attr("y", y)
.attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > 10) {//here I'm checking the length of the text
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan")
.attr("x", 0)
.attr("y", y)
.attr("dy", ++lineNumber * lineHeight + dy + "em")//setting the gap between the label line gaps.
.text(word);
}
}
})
Related
I try to use dx/dy to add offset to group elems after drag, current code not group elements not following mouse move.
var svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 300);
var nodes = [
{
id:"A",
x:50,
y:50,
text:"hello"
}
]
add_box(svg,50,50,nodes)
var tooltip = d3.select('body')
.append('div')
.attr('id','tooltip')
.style('position','absolute')
.style('opacity',0)
.style('background','lightsteelblue')
function add_box(svg,x,y,nodes) {
var g = svg.selectAll('.node')
.data(nodes)
.join('g')
.attr('class','node')
g.call(d3.drag()
.on('start', dragStart)
.on('drag', dragging)
.on('end', dragEnd)
)
var txt = g.append('text')
.text(d => d.text)
.attr('x',d => d.x)
.attr('y',d => d.y)
var bbox = txt.node().getBBox()//getBoundingClientRect()
var m = 2
bbox.x -= m
bbox.y -= m
bbox.width += 2*m
bbox.height += 2*m
var rect = g.append('rect')
.attr('x',bbox.x)
.attr('y',bbox.y)
.attr('width',bbox.width)
.attr('height',bbox.height)
.attr('fill','none')
.attr('stroke','black')
}
function dragStart(event,d){
d3.select(this).raise()
.style("stroke", "")
d3.select('#tooltip')
.transition().duration(100)
.style('opacity', 1)
}
function dragging(event,d){
var x = event.x;
var y = event.y;
var dx = event.dx
var dy = event.dy
d3.select(this).select("text")
.attr("dx", dx)
.attr("dy", dy);
d3.select(this).select("rect")
.attr("dx", dx)
.attr("dy", dy);
var desc = "(" + x.toFixed(1) +"," + y.toFixed(1) + ")"
d3.select('#tooltip')
.style('left', (x+2) + 'px')
.style('top', (y-2) + 'px')
.text(desc)
}
function dragEnd(event,d){
d3.select(this)
.style("stroke", "black")
d3.select('#tooltip').style('opacity', 0)
}
<script src="https://d3js.org/d3.v7.min.js"></script>
I am facing issue to align and wrap big text in Arc segment.
I have tried to implement tspan but unable to transform it correctly.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.arc text,
.wedge text {
font: 10px sans-serif;
text-anchor: middle;
}
.arc path,
.wedge path {
stroke: #fff;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var width = 494,
height = 504,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#f38e36","#d79ae2","#dac2ad","#89e1ea"])
.domain(["Social", "Livability","Knowledge","Economy"]);
var arc = d3.svg.arc()
.outerRadius(radius - 0)
.innerRadius(radius - 110);
var wedge = d3.svg.arc()
.outerRadius(radius - 110)
.innerRadius(0);
var labelWedge = d3.svg.arc()
.outerRadius(radius-200)
.innerRadius(radius-200);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.count; });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
d3.csv("data.csv", type, function(error, data) {
if (error) throw error;
nested = [{"category":"Social","count":25},{"category":"Livability","count":25},{"category":"Knowledge","count":25},{"category":"Economy","count":25}];
data1=
[{"category":"Social","subcategory":"Eduction and Employment","count":0.39},
{"category":"Social","subcategory":"Social Support","count":0.39},
{"category":"Social","subcategory":"Housing & Communities","count":0.39},
{"category":"Social","subcategory":"Civil Society","count":0.39},
{"category":"Livability","subcategory":"Activation and Calendaring","count":0.26},
{"category":"Livability","subcategory":"Mobility","count":0.26},
{"category":"Livability","subcategory":"Nature","count":0.26},
{"category":"Livability","subcategory":"Healthy and Sustainable Lifestyle","count":0.26},
{"category":"Livability","subcategory":"Marketing","count":0.26},
{"category":"Livability","subcategory":"Source of Distinctiveness","count":0.26},
{"category":"Knowledge","subcategory":"Vibrant Tech Companies","count":0.39},
{"category":"Knowledge","subcategory":"Tech Talent Attraction","count":0.39},
{"category":"Knowledge","subcategory":"Distinctive Tech Eduction","count":0.39},
{"category":"Knowledge","subcategory":"Full-Fledge R&D System","count":0.39},
{"category":"Economy","subcategory":"Business Environment Companiesetitiveness","count":0.39},
{"category":"Economy","subcategory":"Tourism","count":0.39},
{"category":"Economy","subcategory":"SME Support","count":0.39},
{"category":"Economy","subcategory":"Private Sector Incentivization","count":0.39}];
console.log("nested", nested);
console.log("nested", data1);
var g = svg.selectAll(".arc")
.data(pie(data1))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.category); });
g.append("text")
.attr("transform", function(d) { return transformLabel(d); })
.attr("dy", ".35em")
.text(function(d) { return d.data.subcategory; });
var g = svg.selectAll(".wedge")
.data(pie(nested))
.enter().append("g")
.attr("class", "wedge");
g.append("path")
.attr("d", wedge)
.style("fill", function(d) { return color(d.data.category); });
g.append("text")
.attr("transform", function(d) { return "translate(" + labelWedge.centroid(d) + ")"; })
.attr("dy", ".35em")
.text(function(d) { return d.data.category; });
});
function type(d) {
d.count = +d.count;
return d;
}
function transformLabel(d){
[x, y] = arc.centroid(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;
let label = "translate(" + [x, y] + ") rotate(-90) rotate(" + rotation + ")";
return label;
}
function wrap(text, width) {
text.each(function () {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
x = text.attr("x"),
y = text.attr("y"),
dy = 0, //parseFloat(text.attr("dy")),
tspan = text.text(null)
.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", ++lineNumber * lineHeight + dy + "em")
.text(word);
}
}
});
}
</script>
calling wrap text not working properly. when I call the wraptext function i got the text but they are mostly not aligned.also what is best option to add the shadow to the each segment of arc.
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 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
I am learning d3, i use the "dataset" variable for the values of the graphic,
i wish use dataset.nombre values for label the d3 graphic, but i can only use dataset.numbers, this is a simplified code version:
<body>
<div id="container2"></div>
<script>
var dataset = {
numbers: [15, 3, 10, 2, 14,17,1],
nombre:["a","b","c","d","e","f","g"]
};
var color = d3.scale.category20();
var pie = d3.layout.pie()
.sort(null);
var piedata = pie(dataset.apples);
var arc = d3.svg.arc()
.innerRadius(radius - 100)
.outerRadius(radius - 50);
var svg = d3.select("#container2").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var path = svg.selectAll("path")
.data(piedata)
.enter().append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc);
svg.selectAll("text").data(piedata)
.enter()
.append("text")
.attr("text-anchor", "middle")
.attr("x", function(d) {
var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
d.cx = Math.cos(a) * (radius - 75);
return d.x = Math.cos(a) * (radius - 20);
})
.attr("y", function(d) {
var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
d.cy = Math.sin(a) * (radius - 75);
return d.y = Math.sin(a) * (radius - 20);
})
.text(function(d) { return d.value; })
.each(function(d) {
var bbox = this.getBBox();
d.sx = d.x - bbox.width/2 - 2;
d.ox = d.x + bbox.width/2 + 2;
d.sy = d.oy = d.y + 5;
});
svg.append("defs").append("marker")
.attr("id", "circ")
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("refX", 3)
.attr("refY", 3)
.append("circle")
.attr("cx", 3)
.attr("cy", 3)
.attr("r", 3);
svg.selectAll("path.pointer").data(piedata).enter()
.append("path")
.attr("class", "pointer")
.style("fill", "none")
.style("stroke", "black")
.attr("marker-end", "url(#circ)")
.attr("d", function(d) {
if(d.cx > d.ox) {
return "M" + d.sx + "," + d.sy + "L" + d.ox + "," + d.oy + " " + d.cx + "," + d.cy;
} else {
return "M" + d.ox + "," + d.oy + "L" + d.sx + "," + d.sy + " " + d.cx + "," + d.cy;
}
});
</script>
</body>
Ideally you'd have objects instead of numbers as the data you pass to the pie layout; then you'd be able to use the data directly. In your case, you can still do so by using the index:
.text(function(d, i) { return dataset.nombre[i]; })
Complete demo here.