Skip to content

Commit

Permalink
feat(pie): Intent to ship pie.outerRadius
Browse files Browse the repository at this point in the history
Implement pie.outerRadius option

Fix #1825
  • Loading branch information
netil authored Dec 23, 2020
1 parent 3474ac0 commit ca67418
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 57 deletions.
36 changes: 36 additions & 0 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -4193,6 +4193,42 @@ d3.select(".chart_area")
}
},
],
OuterRadius: [
{
options: {
data: {
columns: [
["data1", 30],
["data2", 50],
["data3", 20]
],
type: "pie"
},
pie: {
innerRadius: 10,
outerRadius: 100
}
}
},
{
options: {
data: {
columns: [
["data1", 30],
["data2", 50],
["data3", 20]
],
type: "pie"
},
pie: {
outerRadius: {
data1: 110,
data2: 80
}
}
}
},
],
PadAngle: {
options: {
data: {
Expand Down
106 changes: 68 additions & 38 deletions src/ChartInternal/shape/arc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import {interpolate as d3Interpolate} from "d3-interpolate";
import {document} from "../../module/browser";
import CLASS from "../../config/classes";
import {callFn, endall, isFunction, isNumber, isUndefined, setTextValue} from "../../module/util";
import {callFn, endall, isFunction, isNumber, isObject, isUndefined, setTextValue} from "../../module/util";
import {d3Selection} from "../../../types/types";

export default {
Expand Down Expand Up @@ -41,40 +41,57 @@ export default {
updateRadius(): void {
const $$ = this;
const {config, state} = $$;
const radius = config.pie_innerRadius;
const padding = config.pie_padding;
const w = config.gauge_width || config.donut_width;
const gaugeArcWidth = $$.filterTargetsToShow($$.data.targets).length *
config.gauge_arcs_minWidth;

// determine radius
state.radiusExpanded = Math.min(state.arcWidth, state.arcHeight) / 2 * (
$$.hasMultiArcGauge() ? 0.85 : 1);
$$.hasMultiArcGauge() ? 0.85 : 1
);

state.radius = state.radiusExpanded * 0.95;
state.innerRadiusRatio = w ? (state.radius - w) / state.radius : 0.6;

state.gaugeArcWidth = w || (
gaugeArcWidth <= state.radius - state.innerRadius ?
state.radius - state.innerRadius :
(gaugeArcWidth <= state.radius ? gaugeArcWidth : state.radius)
);

const innerRadius = radius || (
const innerRadius = config.pie_innerRadius || (
padding ? padding * (state.innerRadiusRatio + 0.1) : 0
);

// NOTE: innerRadius can be an object by user setting, only for 'pie' type
// NOTE: inner/outerRadius can be an object by user setting, only for 'pie' type
state.outerRadius = config.pie_outerRadius;
state.innerRadius = $$.hasType("donut") || $$.hasType("gauge") ?
state.radius * state.innerRadiusRatio : innerRadius;
},

getInnerRadius(d): number {
/**
* Get pie's inner & outer radius value
* @param {object|undefined} d Data object
* @returns {object}
* @private
*/
getRadius(d): {innerRadius: number, outerRadius: number} {
const $$ = this;
let {innerRadius} = $$.state;
const data = d && d.data;
let {innerRadius, outerRadius} = $$.state;

if (!isNumber(innerRadius) && d) {
innerRadius = innerRadius[d.data.id] || 0;
if (!isNumber(innerRadius) && data) {
innerRadius = innerRadius[data.id] || 0;
}

return innerRadius;
if (isObject(outerRadius) && data && data.id in outerRadius) {
outerRadius = outerRadius[data.id];
} else if (!isNumber(outerRadius)) {
outerRadius = $$.state.radius;
}

return {innerRadius, outerRadius};
},

updateArc(): void {
Expand Down Expand Up @@ -141,25 +158,27 @@ export default {
getSvgArc(): Function {
const $$ = this;
const {state} = $$;
const ir = $$.getInnerRadius();
const singleArcWidth = state.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length;
const hasMultiArcGauge = $$.hasMultiArcGauge();

let arc = d3Arc()
.outerRadius((d: any) => (
hasMultiArcGauge ? (state.radius - singleArcWidth * d.index) : state.radius))
.innerRadius((d: any) => (hasMultiArcGauge ?
state.radius - singleArcWidth * (d.index + 1) :
isNumber(ir) ? ir : 0));
const arc = d3Arc()
.innerRadius((d: any) => {
const {innerRadius} = $$.getRadius(d);

return hasMultiArcGauge ?
state.radius - singleArcWidth * (d.index + 1) :
isNumber(innerRadius) ? innerRadius : 0;
})
.outerRadius((d: any) => {
const {outerRadius} = $$.getRadius(d);

return hasMultiArcGauge ? (state.radius - singleArcWidth * d.index) : outerRadius;
});

const newArc = function(d, withoutUpdate) {
let path: string | null = "M 0 0";

if (d.value || d.data) {
if (!isNumber(ir)) {
arc = arc.innerRadius($$.getInnerRadius(d));
}

const updated = !withoutUpdate && $$.updateAngle(d);

if (withoutUpdate) {
Expand Down Expand Up @@ -189,23 +208,33 @@ export default {
);

const arc = d3Arc()
.outerRadius((d: any) => (hasMultiArcGauge ?
state.radius - singleArcWidth * d.index + expandWidth :
state.radiusExpanded * newRate)
)
.innerRadius((d: any) => (hasMultiArcGauge ?
state.radius - singleArcWidth * (d.index + 1) : state.innerRadius));
.innerRadius((d: any) => (
hasMultiArcGauge ?
state.radius - singleArcWidth * (d.index + 1) : $$.getRadius(d).innerRadius
))
.outerRadius((d: any) => {
let radius: number;

if (hasMultiArcGauge) {
radius = state.radius - singleArcWidth * d.index + expandWidth;
} else {
const {outerRadius} = $$.getRadius(d);
let {radiusExpanded} = state;

if (state.radius !== outerRadius) {
radiusExpanded -= Math.abs(state.radius - outerRadius);
}

radius = radiusExpanded * newRate;
}

return radius;
});

return function(d) {
const updated = $$.updateAngle(d);

if (updated) {
return (
hasMultiArcGauge ? arc : arc.innerRadius($$.getInnerRadius(d))
)(updated);
} else {
return "M 0 0";
}
return updated ? arc(updated) : "M 0 0";
};
},

Expand All @@ -215,7 +244,7 @@ export default {

transformForArcLabel(d): string {
const $$ = this;
const {config, state: {radius, radiusExpanded}} = $$;
const {config, state: {radiusExpanded}} = $$;

const updated = $$.updateAngle(d);
let translate = "";
Expand All @@ -229,6 +258,7 @@ export default {

translate = `translate(${x},${y})`;
} else if (!$$.hasType("gauge") || $$.data.targets.length > 1) {
const {outerRadius} = $$.getRadius(d);
const c = this.svgArc.centroid(updated);
const x = isNaN(c[0]) ? 0 : c[0];
const y = isNaN(c[1]) ? 0 : c[1];
Expand All @@ -238,10 +268,10 @@ export default {
($$.hasType("pie") && config.pie_label_ratio);

if (ratio) {
ratio = isFunction(ratio) ? ratio.bind($$.api)(d, radius, h) : ratio;
ratio = isFunction(ratio) ? ratio.bind($$.api)(d, outerRadius, h) : ratio;
} else {
ratio = radius && (
h ? (36 / radius > 0.375 ? 1.175 - 36 / radius : 0.8) * radius / h : 0
ratio = outerRadius && (
h ? (36 / outerRadius > 0.375 ? 1.175 - 36 / outerRadius : 0.8) * outerRadius / h : 0
);
}

Expand Down
17 changes: 15 additions & 2 deletions src/config/Options/shape/pie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ export default {
* @property {number} [pie.expand.rate=0.98] Set expand rate.
* @property {number} [pie.expand.duration=50] Set expand transition time in ms.
* @property {number|object} [pie.innerRadius=0] Sets the inner radius of pie arc.
* @property {number|object|undefined} [pie.outerRadius=undefined] Sets the outer radius of pie arc.
* @property {number} [pie.padAngle=0] Set padding between data.
* @property {number} [pie.padding=0] Sets the gap between pie arcs.
* @property {object} donut Donut object
* @property {number} [donut.startingAngle=0] Set starting angle where data draws.
* @property {number} [pie.startingAngle=0] Set starting angle where data draws.
* @see [Demo: expand.rate](https://naver.github.io/billboard.js/demo/#PieChartOptions.ExpandRate)
* @see [Demo: innerRadius](https://naver.github.io/billboard.js/demo/#PieChartOptions.InnerRadius)
* @see [Demo: outerRadius](https://naver.github.io/billboard.js/demo/#PieChartOptions.OuterRadius)
* @see [Demo: startingAngle](https://naver.github.io/billboard.js/demo/#PieChartOptions.StartingAngle)
* @example
* pie: {
* label: {
Expand Down Expand Up @@ -65,6 +69,14 @@ export default {
* innerRadius: {
* data1: 10,
* data2: 0
* },
*
* outerRadius: 100,
*
* // set different outerRadius for each data
* outerRadius: {
* data1: 50,
* data2: 100
* }
*
* padAngle: 0.1,
Expand All @@ -80,6 +92,7 @@ export default {
pie_expand_rate: 0.98,
pie_expand_duration: 50,
pie_innerRadius: <number|{[key: string]: number}> 0,
pie_outerRadius: <number|{[key: string]: number}|undefined> undefined,
pie_padAngle: 0,
pie_padding: 0,
pie_startingAngle: 0
Expand Down
3 changes: 2 additions & 1 deletion src/config/Store/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ export default class State {

// value for Arc
radius: 0,
innerRadius: 0,
innerRadius: <{[key: string]: number}|number> 0,
outerRadius: <{[key: string]: number}|number|undefined> undefined,
innerRadiusRatio: 0,
gaugeArcWidth: 0,
radiusExpanded: 0,
Expand Down
2 changes: 1 addition & 1 deletion test/api/zoom-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ describe("API zoom", function() {
expect(this.getTotalLength()).to.be.greaterThan(len[i]);
});

resolve();
resolve(undefined);
}, 300);
}).then(() => {
// when
Expand Down
Loading

0 comments on commit ca67418

Please sign in to comment.