| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- import * as d3 from 'd3';
- export default () => {
- // defaults
- const options = {
- donutWidth: 15,
- endval: 0.66,
- width: 80,
- height: 80,
- duration: 1500,
- colors: [ '#7ED321', '#E3E3E3' ]
- };
- // start
- const donut = selection => {
- const datasetBase = [
- { color: 1, val: 100 }
- ];
- const dataset = [
- { color: 0, val: options.endval * 100 },
- { color: 1, val: 100 - (options.endval * 100) }
- ];
- const radius = Math.min(options.width, options.height) / 2;
- const svg = selection
- .append('svg')
- .attr('width', options.width)
- .attr('height', options.height);
- const arc = d3.arc()
- .innerRadius(radius - options.donutWidth)
- .outerRadius(radius);
- const pie = d3.pie()
- .value(d => d.val)
- .sort(null);
- // base donut without animation 100%
- const groupBase = svg.append('g')
- .attr('transform', `translate(${options.width / 2}, ${options.height / 2})`);
- groupBase.selectAll('path')
- .data(pie(datasetBase))
- .enter()
- .append('path')
- .attr('d', arc)
- .attr('fill', d => options.colors[d.data.color]);
- // fill x% from donut, animate!
- const group = svg.append('g')
- .attr('transform', `translate(${options.width / 2}, ${options.height / 2})`);
- group.selectAll('path')
- .data(pie(dataset))
- .enter()
- .append('path')
- .attr('fill', d => options.colors[d.data.color])
- .transition()
- .delay((d, i) => ((100 - d.value) * options.duration / 100 * i))
- .duration(d => (options.duration * d.value / 100))
- .attrTween('d', d => {
- const i = d3.interpolate(d.startAngle + 0.1, d.endAngle);
- return t => {
- d.endAngle = i(t);
- return arc(d);
- };
- });
- };
- // "setter"
- donut.options = input => {
- Object.assign(options, input);
- return donut;
- };
- return donut;
- };
|