Reputation: 12459
Looking at this fiddle (http://jsfiddle.net/gs6rehnx/2106/), there are four arcs with four different colors. I expect the Pie Chart to have three colors after clicking the update button. However, there are still four arcs. I assue, the mapping of the specific colors to the values
is not working properly? Or is something else not working?
const chart = {};
const duration = 750;
const width = 160;
const height = 160;
const min = Math.min(width, height);
const oRadius = min / 2 * 0.9;
const iRadius = min / 2.5 * 0.85;
const pie = d3
.pie()
.value(function(d) {
return d.value;
})
.sort(null);
const arc = d3
.arc()
.outerRadius(oRadius)
.innerRadius(iRadius);
function arcTween(a) {
const i = d3.interpolate(this._current, a);
this._current = i(0);
return function(t) {
return arc(i(t));
};
};
const labels = ['1', '2', '3', '4'];
const color = ["rgba(126,211,33,1)", "rgba(39,173,232,1)", "rgba(229,5,1,1)", "rgba(245,166,35,1)"];
const scale = d3.scaleOrdinal()
.domain(labels)
.range(color);
const create = function(data) {
const svg = d3
.select('.foo')
.append('svg')
.attr('class', 'pie')
.attr('width', width)
.attr('height', height)
.attr('id', 'svgClass');
svg
.append('g')
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')')
.attr('id', 'bar');
draw(data);
}
const draw = function(data) {
const path = d3.select('#bar')
.selectAll('path')
.data(pie(data))
path
.enter()
.append('g')
.append('path')
.attr('d', arc)
.attr('fill', (d, i) => {
return scale(d.data.name)
});
path
.transition()
.duration(duration)
.attrTween('d', function(d) {
const interpolate = d3.interpolate({
startAngle: 0,
endAngle: 0
}, d);
return function(t) {
return arc(interpolate(t));
};
});
};
const data = [{
"name": "1",
"value": 2
}, {
"name": "2",
"value": 1
}, {
"name": "3",
"value": 2
}, {
"name": "4",
"value": 1
}];
const newData = [{
"name": "1",
"value": 2
}, {
"name": "2",
"value": 1
}, {
"name": "3",
"value": 2
}];
function createPie() {
create(data)
}
function updatePie() {
draw(newData)
}
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js"></script>
<button type="button" onclick="createPie()">Click Me First!</button>
<button type="button" onclick="updatePie()">Update Diagram!</button>
<div class='foo'></div>
Upvotes: 0
Views: 98
Reputation: 34549
The reason this isn't working is because d3
has three main parts to a selection:
In your example above you're dealing with the enter
, the update
isn't quite right and the exit
is completely missing. This is a really good article from the author discussing data joins.
The following grabs all the new
data elements, and adds a new g
element for each one.
path.enter().append('g')
The following which you're missing will take all the items in the DOM that are no longer represented in the data, and remove them.
path.exit().remove();
const chart = {};
const duration = 750;
const width = 160;
const height = 160;
const min = Math.min(width, height);
const oRadius = min / 2 * 0.9;
const iRadius = min / 2.5 * 0.85;
const pie = d3
.pie()
.value(function(d) {
return d.value;
})
.sort(null);
const arc = d3
.arc()
.outerRadius(oRadius)
.innerRadius(iRadius);
function arcTween(a) {
const i = d3.interpolate(this._current, a);
this._current = i(0);
return function(t) {
return arc(i(t));
};
};
const labels = ['1', '2', '3', '4'];
const color = ["rgba(126,211,33,1)", "rgba(39,173,232,1)", "rgba(229,5,1,1)", "rgba(245,166,35,1)"];
const scale = d3.scaleOrdinal()
.domain(labels)
.range(color);
const create = function(data) {
const svg = d3
.select('.foo')
.append('svg')
.attr('class', 'pie')
.attr('width', width)
.attr('height', height)
.attr('id', 'svgClass');
svg
.append('g')
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')')
.attr('id', 'bar');
draw(data);
}
const draw = function(data) {
const path = d3.select('#bar')
.selectAll('path')
.data(pie(data))
path
.enter()
.append('g')
.append('path')
.attr('d', arc)
.attr('fill', (d, i) => {
return scale(d.data.name)
});
path.exit().remove();
path
.transition()
.duration(duration)
.attrTween('d', function(d) {
const interpolate = d3.interpolate({
startAngle: 0,
endAngle: 0
}, d);
return function(t) {
return arc(interpolate(t));
};
});
};
const data = [{
"name": "1",
"value": 2
}, {
"name": "2",
"value": 1
}, {
"name": "3",
"value": 2
}, {
"name": "4",
"value": 1
}];
const newData = [{
"name": "1",
"value": 2
}, {
"name": "2",
"value": 1
}, {
"name": "3",
"value": 2
}];
function createPie() {
create(data)
}
function updatePie() {
draw(newData)
}
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js"></script>
<button type="button" onclick="createPie()">Click Me First!</button>
<button type="button" onclick="updatePie()">Update Diagram!</button>
<div class='foo'></div>
Upvotes: 1