Set max height to an already responsive D3 donut chart - javascript

I have created a donut chart and I am trying to make it responsive. I want the height to have a maximum value. If the window size changes, the donut changes attributes (width and height). Now, I want to set a maximum height value and off course I need the ratio to remain the same. Note that I want the donut chart to be horizontally aligned (same margin from the right and left of the screen).
I have tried changing the values in the width by using the window.innerWidth and innerHeight with no success. I have also tried adding a max attribute for the height in the D3 part of my code.
var dataset = {
numbers: [3200, 5400, 8600]
};
var width = 500,
height = 500,
radius = Math.min(width, height) / 2;
var enterClockwise = {
startAngle: 0,
endAngle: 0
};
var enterAntiClockwise = {
startAngle: Math.PI * 2,
endAngle: Math.PI * 2
};
//var color = d3.scale.category20();
var color = d3.scale.ordinal().range([d3.rgb("#c7003b"), d3.rgb('#000'), d3.rgb('#ccc'),d3.rgb('transparent')])
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 80)
.outerRadius(radius - 40);
var arcThin = d3.svg.arc()
.innerRadius(radius - 65)
.outerRadius(radius - 55);
var svg = d3.select('#Donut-chart').append('svg')
.attr('id', 'Donut-chart-render')
.attr("width", '100%')
.attr("height", '100%')
.attr('viewBox', (-width / 2) + ' ' + (-height / 2) + ' ' + width + ' ' + height)
.attr('preserveAspectRatio', 'xMinYMin').append("g").attr("class", "parent");
var angleData = pie(dataset.numbers);
angleData[1].startAngle = 0;
angleData[1].endAngle = -angleData[1].endAngle + angleData[0].endAngle;
angleData[2].startAngle = angleData[0].endAngle;
angleData[2].endAngle = (2*Math.PI) + angleData[1].endAngle;
var path = svg.selectAll("path")
.data(angleData)
.enter().append("path")
.attr("fill", function (d, i) { return color(i); })
.attr("d", function(d){
return arc(enterClockwise);
})
.each(function (d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterClockwise.startAngle,
endAngle: enterClockwise.endAngle
}
});
path.transition()
.duration(750)
.attrTween("d", arcTween);
function createChart() {
path = path.data(pie(dataset[this.value]));
path.enter().append("path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc(enterAntiClockwise))
.each(function (d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterAntiClockwise.startAngle,
endAngle: enterAntiClockwise.endAngle
};
});
}
function arcTween(a, j) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function (t) {
return (j === (dataset.numbers.length - 1)) ? arcThin(i(t)) : arc(i(t));
};
}
function type(d) {
d.value = +d.value;
return d;
}
#import url(https://fonts.googleapis.com/css?family=Karla);body{font-family:Karla,sans-serif;margin:auto;position:relative}.text{text-anchor:middle;color:#000;font-size:1.7em;font-weight:700;text-transform:uppercase}#legend{align-items:center;border-radius:5px;display:flex;height:0%;justify-content:space-around;width:95%;font-size:25px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.min.js"></script>
<div id="Donut-chart"></div>

Remove width, height and preserveAspectRatio attributes from SVG element and set max-height on it via CSS. Like so:
var dataset = {
numbers: [3200, 5400, 8600]
};
var width = 500,
height = 500,
radius = Math.min(width, height) / 2;
var enterClockwise = {
startAngle: 0,
endAngle: 0
};
var enterAntiClockwise = {
startAngle: Math.PI * 2,
endAngle: Math.PI * 2
};
//var color = d3.scale.category20();
var color = d3.scale.ordinal().range([d3.rgb("#c7003b"), d3.rgb('#000'), d3.rgb('#ccc'),d3.rgb('transparent')])
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 80)
.outerRadius(radius - 40);
var arcThin = d3.svg.arc()
.innerRadius(radius - 65)
.outerRadius(radius - 55);
var svg = d3.select('#Donut-chart').append('svg')
.attr('id', 'Donut-chart-render')
// .attr("width", '100%')
// .attr("height", '100%')
.attr('viewBox', (-width / 2) + ' ' + (-height / 2) + ' ' + width + ' ' + height)
//.attr('preserveAspectRatio', 'xMinYMin')
.append("g").attr("class", "parent");
var angleData = pie(dataset.numbers);
angleData[1].startAngle = 0;
angleData[1].endAngle = -angleData[1].endAngle + angleData[0].endAngle;
angleData[2].startAngle = angleData[0].endAngle;
angleData[2].endAngle = (2*Math.PI) + angleData[1].endAngle;
var path = svg.selectAll("path")
.data(angleData)
.enter().append("path")
.attr("fill", function (d, i) { return color(i); })
.attr("d", function(d){
return arc(enterClockwise);
})
.each(function (d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterClockwise.startAngle,
endAngle: enterClockwise.endAngle
}
});
path.transition()
.duration(750)
.attrTween("d", arcTween);
function createChart() {
path = path.data(pie(dataset[this.value]));
path.enter().append("path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc(enterAntiClockwise))
.each(function (d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterAntiClockwise.startAngle,
endAngle: enterAntiClockwise.endAngle
};
});
}
function arcTween(a, j) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function (t) {
return (j === (dataset.numbers.length - 1)) ? arcThin(i(t)) : arc(i(t));
};
}
function type(d) {
d.value = +d.value;
return d;
}
#Donut-chart svg {
max-height: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.min.js"></script>
<div id="Donut-chart"></div>

Related

Dynamically update D3 half donut chart - how?

I have a d3.js half donut chart showing a progress in %, like this:
The chart gets the json data from a php script with jQuery getJSON function. What I would like is to update the chart every minute, but without having to do a setInterval on the whole script. Is it possible just to replace the chart data every minute?
My chart script:
var w = 300,
h = 300,
outerRadius = (w / 2) - 10,
innerRadius = 85;
var percent = Math.round(json.bhp * 100);
var ratio = percent / 100;
var pie = d3.layout.pie()
.value(function(d){return d})
.sort(null);
var color = ['#ececec','#f6c717','#888888'],
colorOld = '#F00',
colorNew = '#f6c717';
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius)
.startAngle(0)
.endAngle(Math.PI);
var arcLine = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius)
.startAngle(0);
var svg = d3.select('#bhp')
.append('svg')
.attr({
width :w,
height:160,
})
.append('g')
.attr({
transform:'translate('+w/2+','+h/2+')'
});
var path = svg.append('path')
.attr({
d :arc,
transform:'rotate(-90)'
})
.attr({
'stroke-width':"1",
stroke :"#666666"
})
.style({
fill:color[0]
});
var pathForeground = svg.append('path')
.datum({endAngle:0})
.attr({
d :arcLine,
transform:'rotate(-90)'
})
.style({
fill: function (d, i) {
return color[1];
}
});
var middleCount_bhp = svg.append('text')
.datum(0)
.text(function(d){
return d;
})
.attr({
class :'middleText',
'text-anchor':'middle',
dy :0,
dx :5
})
.style({
fill :d3.rgb('#000000'),
'font-size':'60px'
});
var oldValue = 0;
var arcTween = function(transition, newValue, oldValue) {
transition.attrTween('d', function (d) {
var interpolate = d3.interpolate(d.endAngle, ((Math.PI)) * (newValue / 100));
var interpolateCount = d3.interpolate(oldValue, newValue);
return function (t) {
d.endAngle = interpolate(t);
middleCount_bhp.text(Math.floor(interpolateCount(t)) + '%');
return arcLine(d);
};
});
};
pathForeground.transition()
.delay(200)
.duration(750)
.ease('cubic')
.call(arcTween, percent, oldValue);

animate arc start angle with d3.js

I am trying to animate the start angle of the arc using D3.js
Any help or link for reference would do.
I have tried the below:
http://jsfiddle.net/87e3d4tj/
d3.select('#my-path').datum({
startAngle: endAngle,
endAngle: ( 90 * (Math.PI/180) )
})
.transition()
.duration(duration)
.attrTween('d', d => {
var interpolate = d3.interpolate(d.startAngle, d.endAngle);
return function(t) {
d.endAngle = endAngle;
d.startAngle = interpolate(t);
return arc(d);
};
});
i have tried the below hope you are looking for the same.
https://jsfiddle.net/debasish007/eu7xo4mL/
var width = 400,
height = 400,
τ = (Math.PI/180);
var arc = d3.arc()
.innerRadius(130)
.outerRadius(150);
var svg = d3.select("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
var foreground = svg.append("path")
.datum({
endAngle: 90 * τ,
startAngle: -90 * τ
})
.style("fill", "blue")
.attr("d", arc);
setTimeout(function () {
foreground.transition()
.duration(750)
.call(arcTween, -30 * τ, 90 * τ);
}, 1500);
function arcTween(transition, newStartAngle, newFinishAngle) {
transition.attrTween("d", function (d) {
var interpolateStart = d3.interpolate(d.startAngle, newStartAngle);
return function (t) {
d.endAngle = newFinishAngle;
d.startAngle = interpolateStart(t);
return arc(d);
};
});
}

D3 donut chart for negative (anticlockwise) and positive (clockwise) (Angle being dynamic)

I get a JSON query and I want to present a positive (red) and negative (black) segment in the same graph. The positive is the first number in the JSON and the negative is the second one.
var dataset = {
numbers: [3200, 5400, 8600]
};
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var enterClockwise = {
startAngle: 0,
endAngle: 0
};
var enterAntiClockwise = {
startAngle: Math.PI * 2,
endAngle: Math.PI * 2
};
//var color = d3.scale.category20();
var color = d3.scale.ordinal().range([d3.rgb("#c7003b"), d3.rgb('#000'), d3.rgb('#ccc'),d3.rgb('transparent')])
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 80)
.outerRadius(radius - 40);
var arcThin = d3.svg.arc()
.innerRadius(radius - 65)
.outerRadius(radius - 55);
var svg = d3.select('#Donut-chart').append('svg')
.attr('id', 'Donut-chart-render')
.attr("width", '100%')
.attr("height", '100%')
.attr('viewBox', (-width / 2) + ' ' + (-height / 2) + ' ' + width + ' ' + height)
.attr('preserveAspectRatio', 'xMinYMin')
var path = svg.selectAll("path")
.data(pie(dataset.numbers))
.enter().append("path")
.attr("fill", function (d, i) { return color(i); })
.attr("d", function(d){
return arc(enterClockwise);
})
.each(function (d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterClockwise.startAngle,
endAngle: enterClockwise.endAngle
}
});
path.transition()
.duration(750)
.attrTween("d", arcTween);
function createChart() {
path = path.data(pie(dataset[this.value]));
path.enter().append("path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc(enterAntiClockwise))
.each(function (d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterAntiClockwise.startAngle,
endAngle: enterAntiClockwise.endAngle
};
});
}
function arcTween(a, j) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function (t) {
return (j === (dataset.numbers.length - 1)) ? arcThin(i(t)) : arc(i(t));
};
}
/*
function arcTweenOut(a, j) {
var i = d3.interpolate(this._current, { startAngle: Math.PI * 2, endAngle: Math.PI * 2, value: 0 });
this._current = i(0);
return function (t) {
console.log(j === dataset.length - 1)
return arc(i(t));
};
}
*/
function type(d) {
d.value = +d.value;
return d;
}
createChart(dataset);
#import url(https://fonts.googleapis.com/css?family=Karla);body{font-family:Karla,sans-serif;margin:auto;position:relative}.text{text-anchor:middle;color:#000;font-size:1.7em;font-weight:700;text-transform:uppercase}#legend{align-items:center;border-radius:5px;display:flex;height:0%;justify-content:space-around;width:95%;font-size:25px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.min.js"></script>
<div id="Donut-chart"></div>
So, basically I want it to looks like this:
The positive will start from point 0 clockwise and the negative will start from the same point but anticlockwise.
I had an idea of using the following:
.each(function (d, i=0) {
console.log(i);
i++;
if(i == 1){
this._current = {
data: d.data,
value: d.value,
startAngle: enterAntiClockwise.startAngle,
endAngle: enterAntiClockwise.endAngle
}
}
else{
this._current = {
data: d.data,
value: d.value,
startAngle: enterClockwise.startAngle,
endAngle: enterClockwise.endAngle
}
}
});
which didn't work.
Simplest solution is to manipulate your data before appending the path.
var angleData = pie(dataset.numbers);
angleData[1].startAngle = 0;
angleData[1].endAngle = -angleData[1].endAngle + angleData[0].endAngle; // finding the clockwise angle
angleData[2].startAngle = angleData[0].endAngle; // shifting position of third arc
angleData[2].endAngle = (2*Math.PI) + angleData[1].endAngle;
var dataset = {
numbers: [3200, 5400, 8600]
};
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var enterClockwise = {
startAngle: 0,
endAngle: 0
};
var enterAntiClockwise = {
startAngle: Math.PI * 2,
endAngle: Math.PI * 2
};
//var color = d3.scale.category20();
var color = d3.scale.ordinal().range([d3.rgb("#c7003b"), d3.rgb('#000'), d3.rgb('#ccc'),d3.rgb('transparent')])
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 80)
.outerRadius(radius - 40);
var arcThin = d3.svg.arc()
.innerRadius(radius - 65)
.outerRadius(radius - 55);
var svg = d3.select('#Donut-chart').append('svg')
.attr('id', 'Donut-chart-render')
.attr("width", '100%')
.attr("height", '100%')
.attr('viewBox', (-width / 2) + ' ' + (-height / 2) + ' ' + width + ' ' + height)
.attr('preserveAspectRatio', 'xMinYMin').append("g").attr("class", "parent");
var angleData = pie(dataset.numbers);
angleData[1].startAngle = 0;
angleData[1].endAngle = -angleData[1].endAngle + angleData[0].endAngle;
angleData[2].startAngle = angleData[0].endAngle;
angleData[2].endAngle = (2*Math.PI) + angleData[1].endAngle;
var path = svg.selectAll("path")
.data(angleData)
.enter().append("path")
.attr("fill", function (d, i) { return color(i); })
.attr("d", function(d){
return arc(enterClockwise);
})
.each(function (d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterClockwise.startAngle,
endAngle: enterClockwise.endAngle
}
});
path.transition()
.duration(750)
.attrTween("d", arcTween);
function createChart() {
path = path.data(pie(dataset[this.value]));
path.enter().append("path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc(enterAntiClockwise))
.each(function (d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterAntiClockwise.startAngle,
endAngle: enterAntiClockwise.endAngle
};
});
}
function arcTween(a, j) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function (t) {
return (j === (dataset.numbers.length - 1)) ? arcThin(i(t)) : arc(i(t));
};
}
/*
function arcTweenOut(a, j) {
var i = d3.interpolate(this._current, { startAngle: Math.PI * 2, endAngle: Math.PI * 2, value: 0 });
this._current = i(0);
return function (t) {
console.log(j === dataset.length - 1)
return arc(i(t));
};
}
*/
function type(d) {
d.value = +d.value;
return d;
}
#import url(https://fonts.googleapis.com/css?family=Karla);body{font-family:Karla,sans-serif;margin:auto;position:relative}.text{text-anchor:middle;color:#000;font-size:1.7em;font-weight:700;text-transform:uppercase}#legend{align-items:center;border-radius:5px;display:flex;height:0%;justify-content:space-around;width:95%;font-size:25px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.min.js"></script>
<div id="Donut-chart"></div>

Multi donut graph with curved borders

I am trying to create a doughnut graph with curved ends. This graph has multiple series in it.
I have also found a fiddle which is similar to my needs: jsfiddle.net/freezystem/henr4ozn/
But this is in v3 and I have been trying to convert it to v4, but failing to render the graph.
As per the comments and complexity I have dropped the conversion of above jsfiddle to v4 and I am trying to convert this jsfiddle.net/minnie_mouse/033jrrz8/ to v4
But still I am not getting the same rendered image.
const d3 = this.d3;
const arcTween = function (transition, newAngle, arc) {
transition.attrTween('d', function (d) {
const interpolate = d3.interpolate(d.endAngle, newAngle);
return function (t) {
d.endAngle = interpolate(t);
return arc(d);
};
});
};
const createCircle = function (svg, outerRadius, innerRadius, color, percent) {
debugger;
const ratio = percent / 100;
const arcBackground = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius)
.startAngle(0)
.endAngle(2 * Math.PI);
const pathBackground = svg.append('path')
.attr('d', arcBackground)
.style({
fill: '#585e65',
opacity: .2
});
const arcForeground = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius)
.cornerRadius(20)
.startAngle(-0.05);
const pathForeground = svg.append('path')
.datum({ endAngle: 0 })
.attr('d', arcBackground)
.style({
fill: color
}).append('text')
.attr('transform', 'translate(10,10)')
.text('hi')
.attr('fill', 'white')
.attr('font-size', '20px');
pathForeground.transition()
.duration(1500)
.ease('elastic')
.call(arcTween, ((2 * Math.PI)) * ratio, arcForeground);
const chart = { path: pathForeground, arc: arcForeground };
return chart;
};
const addStartImage = function (svg, percent, outerRadius) {
svg.append('text')
.text(percent + '%')
.attr('font-size', '10px')
.attr('font-weight', 'bold')
.attr('fill', 'white')
.attr({
width: 20,
height: 20,
transform: 'translate(4,' + (-outerRadius + 20) + ')'
});
};
const w = 300, h = 300;
let outerRadius = (w / 2);
const width = 30, gap = 14;
const innerRadius = outerRadius - 30;
const color = ['#e90b3a', '#a0ff03', '#1ad5de'];
const svg = d3.select('#chart')
.append('svg')
.attr('width', w)
.attr('height', h)
.attr('class', 'shadow')
.append('g')
.attr('transform', 'translate(' + w / 2 + ',' + h / 2 + ')'
);
const circles = [
{ name: 'activity1', percent: 50, color: '#3e4eb7' },
{ name: 'activity2', percent: 66, color: '#50a7ff' }];
for (let i = 0; i < circles.length; ++i) {
if (i > 0) {
outerRadius = innerRadius - gap;
}
circles[i]['chart'] = createCircle(svg, outerRadius, innerRadius, circles[i].color, circles[i].percent);
addStartImage(svg, circles[i].percent, outerRadius);
}
Atlast I got it to run successfully.Here is the code
const d3 = this.d3;
const arcTween = function (transition, newAngle, arc) {
transition.attrTween('d', function (d) {
const interpolate = d3.interpolate(d.endAngle, newAngle);
return function (t) {
d.endAngle = interpolate(t);
return arc(d);
};
});
};
const createCircle = function (svg, outerRadius, innerRadius, color, percent) {
const ratio = percent / 100;
const arcBackground = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius)
.startAngle(0)
.endAngle(2 * Math.PI);
const pathBackground = svg.append('path')
.attr('d', arcBackground)
.style({
fill: '#585e65',
opacity: .2
});
const arcForeground = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius)
.cornerRadius(20)
.startAngle(-0.05);
const pathForeground = svg.append('path')
.datum({ endAngle: 0 })
.attr('d', arcBackground)
.style('fill', color);
pathForeground.append('text')
.attr('transform', 'translate(10,10)')
.text('hi')
.attr('fill', 'white')
.attr('font-size', '20px');
pathForeground.transition()
.duration(2000)
.transition()
.ease(d3.easeElastic)
.call(arcTween, ((2 * Math.PI)) * ratio, arcForeground);
const chart = { path: pathForeground, arc: arcForeground };
return chart;
};
const addStartImage = function (svg, percent, outerRadius) {
svg.append('text')
.text(percent + '%')
.attr('font-size', '10px')
.attr('font-weight', 'bold')
.attr('fill', 'white')
.attr({
width: 20,
height: 20,
transform: 'translate(4,' + (-outerRadius + 20) + ')'
});
};
const w = 300, h = 300;
let outerRadius = (w / 2);
const width = 30, gap = 14;
const innerRadius = outerRadius - 30;
const color = ['#e90b3a', '#a0ff03', '#1ad5de'];
const svg = d3.select('#chart')
.append('svg')
.attr('width', w)
.attr('height', h)
.attr('class', 'shadow')
.append('g')
.attr('transform', 'translate(' + w / 2 + ',' + h / 2 + ')'
);
const circles = [
{ name: 'activity1', percent: 50, color: '#3e4eb7' },
{ name: 'activity2', percent: 66, color: '#50a7ff' }];
for (let i = 0; i < circles.length; ++i) {
if (i > 0) {
outerRadius = innerRadius - gap;
}
circles[i]['chart'] = createCircle(svg, outerRadius, innerRadius, circles[i].color, circles[i].percent);
addStartImage(svg, circles[i].percent, outerRadius);
}

D3 Pie Chart Update, IV in while loop not working well - why?

I work for the first time with the D3 library and basically also with javascript and i rly need some help.
I want to create this beautiful pie chart in a while loop when the mysql-query is true. It works. It makes three pie charts and the associated forms with the radio inputs. But after that, only the last pie chart works when I want to switch the radio buttons value. The other two pie charts dont switch their value when I activate the unselected radio button.
What should i do?
<?php
$gem_stud_data = $db->prepare("SELECT * FROM ergebnisse WHERE studiengang_1 <> 0 AND studiengang_2 <> 0 AND semester_id=1");
$gem_stud_data->execute();
if($_GET["id"] == 1){
while($gem_stud_datas = $gem_stud_data->fetch()){
$stud1_data = $db->prepare("SELECT * FROM studiengaenge WHERE id=:eins");
$stud1_data->bindParam(":eins", $gem_stud_datas["studiengang_1"]);
$stud1_data->execute();
$stud1_datas = $stud1_data->fetch();
$stud2_data = $db->prepare("SELECT * FROM studiengaenge WHERE id=:eins");
$stud2_data->bindParam(":eins", $gem_stud_datas["studiengang_2"]);
$stud2_data->execute();
$stud2_datas = $stud2_data->fetch();
?>
<form>
<label><input type="radio" name="dataset" value="stud_1" checked> <?php echo $stud1_datas["kuerzel"]; ?></label>
<label><input type="radio" name="dataset" value="stud_2"> <?php echo $stud2_datas["kuerzel"]; ?></label>
</form>
<script>
var dataset = {
stud_1: [53245, 28479, 19697, 24037, 40245],
stud_2: [200, 200, 200, 200]
};
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var enterClockwise = {
startAngle: 0,
endAngle: 0
};
var enterAntiClockwise = {
startAngle: Math.PI * 2,
endAngle: Math.PI * 2
};
var color = d3.scale.category20();
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 100)
.outerRadius(radius - 20);
var svg = d3.select("main").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// set the start and end angles to 0 so we can transition
// clockwise to the actual values later
var path = svg.selectAll("path")
.data(pie(dataset.stud_1))
.enter().append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc(enterClockwise))
.each(function(d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterClockwise.startAngle,
endAngle: enterClockwise.endAngle
}
}); // store the initial values
path.transition() // update
.duration(750)
.attrTween("d", arcTween);
d3.selectAll("input").on("change", change);
var timeout = setTimeout(function() {
d3.select("input[value=\"stud_2\"]").property("checked", true).each(change);
}, 2000);
function change() {
clearTimeout(timeout);
path = path.data(pie(dataset[this.value])); // update the data
// set the start and end angles to Math.PI * 2 so we can transition
// anticlockwise to the actual values later
path.enter().append("path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc(enterAntiClockwise))
.each(function (d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterAntiClockwise.startAngle,
endAngle: enterAntiClockwise.endAngle
};
}); // store the initial values
path.exit()
.transition()
.duration(750)
.attrTween('d', arcTweenOut)
.remove() // now remove the exiting arcs
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));
};
}
function arcTweenOut(a) {
var i = d3.interpolate(this._current, {startAngle: Math.PI * 2, endAngle: Math.PI * 2, value: 0});
this._current = i(0);
return function (t) {
return arc(i(t));
};
}
</script>
<?php
}
} ?>
I really hope you can help me! I am very frustrated :(
I thank you in advance!
Please see below, this works for me and changes the data on the timeout you created.
<form>
<label><input type="radio" name="dataset" value="stud_1" checked> Option 1 </label>
<label><input type="radio" name="dataset" value="stud_2"> Option 2 </label>
</form>
<script>
var dataset = {
stud_1: [53245, 28479, 19697, 24037, 40245],
stud_2: [200, 200, 200, 200]
};
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var enterClockwise = {
startAngle: 0,
endAngle: 0
};
var enterAntiClockwise = {
startAngle: Math.PI * 2,
endAngle: Math.PI * 2
};
var color = d3.scale.category20();
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 100)
.outerRadius(radius - 20);
var svg = d3.select("#main").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// set the start and end angles to 0 so we can transition
// clockwise to the actual values later
var path = svg.selectAll("path")
.data(pie(dataset.stud_1))
.enter().append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc(enterClockwise))
.each(function(d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterClockwise.startAngle,
endAngle: enterClockwise.endAngle
}
}); // store the initial values
path.transition() // update
.duration(750)
.attrTween("d", arcTween);
d3.selectAll("input").on("change", change);
var timeout = setTimeout(function() {
d3.select("input[value=\"stud_2\"]").property("checked", true).each(change);
}, 2000);
function change() {
clearTimeout(timeout);
path = path.data(pie(dataset[this.value])); // update the data
// set the start and end angles to Math.PI * 2 so we can transition
// anticlockwise to the actual values later
path.enter().append("path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc(enterAntiClockwise))
.each(function (d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterAntiClockwise.startAngle,
endAngle: enterAntiClockwise.endAngle
};
}); // store the initial values
path.exit()
.transition()
.duration(750)
.attrTween('d', arcTweenOut)
.remove() // now remove the exiting arcs
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));
};
}
function arcTweenOut(a) {
var i = d3.interpolate(this._current, {startAngle: Math.PI * 2, endAngle: Math.PI * 2, value: 0});
this._current = i(0);
return function (t) {
return arc(i(t));
};
}
</script>
See revised solution ... there you must grab all svgs and then select the paths and then append data ... see change in the change function.
<form>
<label><input type="radio" name="dataset" value="stud_1" checked> Option 1 </label>
<label><input type="radio" name="dataset" value="stud_2"> Option 2 </label>
</form>
<script>
var dataset = {
stud_1: [53245, 28479, 19697, 24037, 40245],
stud_2: [200, 200, 200, 200]
};
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var enterClockwise = {
startAngle: 0,
endAngle: 0
};
var enterAntiClockwise = {
startAngle: Math.PI * 2,
endAngle: Math.PI * 2
};
var color = d3.scale.category20();
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 100)
.outerRadius(radius - 20);
var svg = d3.select("#main").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 3 + "," + height / 3 + ")");
var svg2 = d3.select("#main2").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + (width / 3 * 2) + "," + (height / 3 * 2) + ")");
var svg3 = d3.select("#main3").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + (width / 3 * 2) + "," + (height / 3 * 2)+ ")");
// set the start and end angles to 0 so we can transition
// clockwise to the actual values later
var path = d3.selectAll('svg').selectAll("path")
.data(pie(dataset.stud_1))
.enter().append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc(enterClockwise))
.each(function(d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterClockwise.startAngle,
endAngle: enterClockwise.endAngle
}
}); // store the initial values
path.transition() // update
.duration(750)
.attrTween("d", arcTween);
d3.selectAll("input").on("change", change);
var timeout = setTimeout(function() {
d3.select("input[value=\"stud_2\"]").property("checked", true).each(change);
}, 2000);
function change() {
clearTimeout(timeout);
path = d3.selectAll('svg').selectAll('path').data(pie(dataset[this.value])); // update the data
// set the start and end angles to Math.PI * 2 so we can transition
// anticlockwise to the actual values later
path.enter().append("path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc(enterAntiClockwise))
.each(function (d) {
this._current = {
data: d.data,
value: d.value,
startAngle: enterAntiClockwise.startAngle,
endAngle: enterAntiClockwise.endAngle
};
}); // store the initial values
path.exit()
.transition()
.duration(750)
.attrTween('d', arcTweenOut)
.remove() // now remove the exiting arcs
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));
};
}
function arcTweenOut(a) {
var i = d3.interpolate(this._current, {startAngle: Math.PI * 2, endAngle: Math.PI * 2, value: 0});
this._current = i(0);
return function (t) {
return arc(i(t));
};
}
</script>

Categories