diff --git a/demo/demo.js b/demo/demo.js index be4b58b46..10bd2f8ff 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -3343,21 +3343,42 @@ d3.select(".chart_area") } } }, - InnerRadius: { - options: { - data: { - columns: [ - ["data1", 30], - ["data2", 50], - ["data3", 20] - ], - type: "pie" - }, - pie: { - innerRadius: 20 + InnerRadius: [ + { + options: { + data: { + columns: [ + ["data1", 30], + ["data2", 50], + ["data3", 20] + ], + type: "pie" + }, + pie: { + innerRadius: 20 + } } - } - }, + }, + { + options: { + data: { + columns: [ + ["data1", 30], + ["data2", 50], + ["data3", 20] + ], + type: "pie" + }, + pie: { + innerRadius: { + data1: 50, + data2: 80, + data3: 0 + } + } + } + }, + ], PadAngle: { options: { data: { diff --git a/spec/shape/shape.arc-spec.js b/spec/shape/shape.arc-spec.js index cdffe2259..74dcc9147 100644 --- a/spec/shape/shape.arc-spec.js +++ b/spec/shape/shape.arc-spec.js @@ -182,6 +182,43 @@ describe("SHAPE ARC", () => { expect(value).to.be.equal(d.value); }); }); + + it("check for variant innerRadius", done => { + const innerRadius = { + data1: 50, + data2: 80, + data3: 0 + }; + const chart = util.generate({ + data: { + columns: [ + ["data1", 30], + ["data2", 50], + ["data3", 20] + ], + type: "pie" + }, + pie: { + innerRadius + } + }); + + const expected = { + data1: "M-8.110822788676742e-14,211.85A211.85,211.85,0,0,1,-201.48132297712823,-65.46525025833276L-47.55282581475767,-15.450849718747406A50,50,0,0,0,-1.9142843494634746e-14,50Z", + data2: "M1.2972071219968338e-14,-211.85A211.85,211.85,0,1,1,-8.110822788676742e-14,211.85L-3.06285495914156e-14,80A80,80,0,1,0,4.898587196589413e-15,-80Z", + data3: "M-201.48132297712823,-65.46525025833276A211.85,211.85,0,0,1,1.4924438455356651e-13,-211.85L0,0Z" + }; + + expect(chart.internal.innerRadius).to.be.deep.equal(innerRadius); + + setTimeout(() => { + chart.$.arc.selectAll("path").each(function(d) { + expect(this.getAttribute("d")).to.be.equal(expected[d.data.id]); + }); + + done(); + }, 500); + }); }); describe("show gauge", () => { diff --git a/src/config/Options.js b/src/config/Options.js index ab8e7b9bb..bb34daa08 100644 --- a/src/config/Options.js +++ b/src/config/Options.js @@ -2947,7 +2947,7 @@ export default class Options { * @property {Number|Function} [pie.label.ratio=undefined] Set ratio of labels position. * @property {Boolean|Object} [pie.expand=true] Enable or disable expanding pie pieces. * @property {Number} [pie.expand.duration=50] Set expand transition time in ms. - * @property {Number} [pie.innerRadius=0] Sets the inner radius of pie arc. + * @property {Number|Object} [pie.innerRadius=0] Sets the inner radius of pie arc. * @property {Number} [pie.padAngle=0] Set padding between data. * @property {Number} [pie.padding=0] Sets the gap between pie arcs. * @example @@ -2980,6 +2980,13 @@ export default class Options { * }, * * innerRadius: 0, + * + * // set different innerRadius for each data + * innerRadius: { + * data1: 10, + * data2: 0 + * } + * * padAngle: 0.1, * padding: 0 * } diff --git a/src/shape/arc.js b/src/shape/arc.js index 58494fa31..49457b9c3 100644 --- a/src/shape/arc.js +++ b/src/shape/arc.js @@ -13,7 +13,7 @@ import { import {interpolate as d3Interpolate} from "d3-interpolate"; import ChartInternal from "../internals/ChartInternal"; import CLASS from "../config/classes"; -import {extend, isFunction, isUndefined} from "../internals/util"; +import {extend, isFunction, isNumber, isUndefined} from "../internals/util"; extend(ChartInternal.prototype, { initPie() { @@ -47,10 +47,22 @@ extend(ChartInternal.prototype, { padding ? padding * ($$.innerRadiusRatio + 0.1) : 0 ); + // NOTE: innerRadius can be an object by user setting, only for 'pie' type $$.innerRadius = $$.hasType("donut") || $$.hasType("gauge") ? $$.radius * $$.innerRadiusRatio : innerRadius; }, + getInnerRadius(d) { + const $$ = this; + let radius = $$.innerRadius; + + if (!isNumber(radius) && d) { + radius = radius[d.data.id] || 0; + } + + return radius; + }, + updateArc() { const $$ = this; @@ -109,14 +121,19 @@ extend(ChartInternal.prototype, { getSvgArc() { const $$ = this; - const arc = d3Arc() + const ir = $$.getInnerRadius(); + let arc = d3Arc() .outerRadius($$.radius) - .innerRadius($$.innerRadius); + .innerRadius(isNumber(ir) ? ir : 0); const newArc = (d, withoutUpdate) => { let path = "M 0 0"; if ("value" in d ? d.value > 0 : d.data) { + if (!isNumber(ir)) { + arc = arc.innerRadius($$.getInnerRadius(d)); + } + const updated = !withoutUpdate && $$.updateAngle(d); if (withoutUpdate) { @@ -138,13 +155,12 @@ extend(ChartInternal.prototype, { getSvgArcExpanded(rate) { const $$ = this; const arc = d3Arc() - .outerRadius($$.radiusExpanded * (rate || 1)) - .innerRadius($$.innerRadius); + .outerRadius($$.radiusExpanded * (rate || 1)); return function(d) { const updated = $$.updateAngle(d); - return updated ? arc(updated) : "M 0 0"; + return updated ? arc.innerRadius($$.getInnerRadius(d))(updated) : "M 0 0"; }; }, @@ -640,8 +656,6 @@ extend(ChartInternal.prototype, { .style("opacity", "0") .attr("class", d => ($$.isGaugeType(d.data) ? CLASS.gaugeValue : null)); - config.gauge_fullCircle && text.attr("dy", `${Math.round($$.radius / 14)}`); - text.call($$.textForArcLabel.bind($$)) .attr("transform", $$.transformForArcLabel.bind($$)) .style("font-size", d => ($$.isGaugeType(d.data) ? `${Math.round($$.radius / 5)}px` : "")) @@ -653,7 +667,10 @@ extend(ChartInternal.prototype, { .style("opacity", $$.hasType("donut") || $$.hasType("gauge") ? "1" : "0"); if ($$.hasType("gauge")) { - const endAngle = (config.gauge_fullCircle ? -4 : -1) * config.gauge_startingAngle; + const isFullCircle = config.gauge_fullCircle; + const endAngle = (isFullCircle ? -4 : -1) * config.gauge_startingAngle; + + isFullCircle && text.attr("dy", `${Math.round($$.radius / 14)}`); $$.arcs.select(`.${CLASS.chartArcsBackground}`) .attr("d", () => { @@ -677,7 +694,7 @@ extend(ChartInternal.prototype, { .text($$.textForGaugeMinMax(config.gauge_min, false)); // show max text when isn't fullCircle - !config.gauge_fullCircle && $$.arcs.select(`.${CLASS.chartArcsGaugeMax}`) + !isFullCircle && $$.arcs.select(`.${CLASS.chartArcsGaugeMax}`) .attr("dx", `${$$.innerRadius + (($$.radius - $$.innerRadius) / 2)}px`) .attr("dy", "1.2em") .text($$.textForGaugeMinMax(config.gauge_max, true)); diff --git a/types/options.d.ts b/types/options.d.ts index 36e49ecfa..4b49fe296 100644 --- a/types/options.d.ts +++ b/types/options.d.ts @@ -385,7 +385,10 @@ export interface ChartOptions { /** * Sets the inner radius of pie arc. */ - innerRadius?: number; + innerRadius?: number | { + [key: string]: number + + }; /** * Set padding between data.