From e19c44b7c274e286fc37cca2495458c8299e622d Mon Sep 17 00:00:00 2001 From: netil Date: Wed, 7 Feb 2024 15:14:20 +0900 Subject: [PATCH] feat(gauge): Intent to ship gauge.label.ratio Implement gauge.label.ratio option Ref #3633 --- demo/demo.js | 73 +++++++++++++++++++++++++++++ src/ChartInternal/shape/arc.ts | 2 +- src/config/Options/shape/gauge.ts | 15 +++++- src/config/Options/shape/pie.ts | 4 +- test/shape/gauge-spec.ts | 78 +++++++++++++++++++++++++++++++ types/options.shape.d.ts | 5 ++ 6 files changed, 172 insertions(+), 5 deletions(-) diff --git a/demo/demo.js b/demo/demo.js index 554fa2423..3b4496bfd 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -5744,6 +5744,79 @@ setTimeout(function() { } } }, + GaugeLabelRatio: [ + { + options: { + title: { + text: "Default label ratio" + }, + size: { + height: 200 + }, + data: { + columns: [ + ["data1", 100], + ["data2", 70], + ["data3", 30] + ], + type: "gauge", + }, + gauge: { + width: 80 + } + } + }, + { + options: { + title: { + text: "To make label text centered" + }, + size: { + height: 200 + }, + data: { + columns: [ + ["data1", 100], + ["data2", 70], + ["data3", 30] + ], + type: "gauge", + }, + gauge: { + width: 80, + label: { + ratio: 1 + } + } + } + }, + { + options: { + title: { + text: "Customize label ratio by function" + }, + size: { + height: 200 + }, + data: { + columns: [ + ["data1", 100], + ["data2", 70], + ["data3", 30] + ], + type: "gauge", + }, + gauge: { + width: 80, + label: { + ratio: function(d, radius, h) { + return d.value >= 100 ? 0.6 : 1.3; + } + } + } + } + } + ], GaugeNeedle: [ { options: { diff --git a/src/ChartInternal/shape/arc.ts b/src/ChartInternal/shape/arc.ts index be202cf57..c29161149 100644 --- a/src/ChartInternal/shape/arc.ts +++ b/src/ChartInternal/shape/arc.ts @@ -405,7 +405,7 @@ export default { const [x, y] = c.map(v => (isNaN(v) ? 0 : v)); const h = Math.sqrt(x * x + y * y); - let ratio = ["donut", "pie", "polar"] + let ratio = ["donut", "gauge", "pie", "polar"] .filter($$.hasType.bind($$)) .map(v => config[`${v}_label_ratio`])?.[0]; diff --git a/src/config/Options/shape/gauge.ts b/src/config/Options/shape/gauge.ts index 2f3f793a1..ac7f6eed1 100644 --- a/src/config/Options/shape/gauge.ts +++ b/src/config/Options/shape/gauge.ts @@ -15,12 +15,13 @@ export default { * @property {boolean} [gauge.background=""] Set background color. (The `.bb-chart-arcs-background` element) * @property {boolean} [gauge.fullCircle=false] Show full circle as donut. When set to 'true', the max label will not be showed due to start and end points are same location. * @property {boolean} [gauge.label.show=true] Show or hide label on gauge. + * @property {Function} [gauge.label.extents] Set customized min/max label text. * @property {Function} [gauge.label.format] Set formatter for the label on gauge. Label text can be multilined with `\n` character.
* Will pass following arguments to the given function: * - value {number}: absolute value * - ratio {number}: value's ratio * - id {string}: data's id value - * @property {Function} [gauge.label.extents] Set customized min/max label text. + * @property {number|Function} [gauge.label.ratio=undefined] Set ratio of labels position. * @property {number} [gauge.label.threshold=0] Set threshold ratio to show/hide labels. * @property {boolean} [gauge.expand=true] Enable or disable expanding gauge. * @property {number} [gauge.expand.rate=0.98] Set expand rate. @@ -61,6 +62,7 @@ export default { * @see [Demo: enforceMinMax, min/max](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeMinMax) * @see [Demo: archLength](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeArcLength) * @see [Demo: startingAngle](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeStartingAngle) + * @see [Demo: labelRatio](https://naver.github.io/billboard.js/demo/#GaugeChartOptions.GaugeLabelRatio) * @example * gauge: { * background: "#eee", // will set 'fill' css prop for '.bb-chart-arcs-background' classed element. @@ -81,6 +83,14 @@ export default { * // 0.1(10%) ratio value means, the minimum ratio to show text label relative to the total value. * // if data value is below than 0.1, text label will be hidden. * threshold: 0.1, + * + * // set ratio callback. Should return ratio value + * ratio: function(d, radius, h) { + * ... + * return ratio; + * }, + * // or set ratio number + * ratio: 0.5 * }, * * // disable expand transition for interaction @@ -119,8 +129,9 @@ export default { gauge_background: "", gauge_fullCircle: false, gauge_label_show: true, - gauge_label_format: <(() => string)|undefined> undefined, gauge_label_extents: <(() => string)|undefined> undefined, + gauge_label_format: <(() => string)|undefined> undefined, + gauge_label_ratio: <(() => number)|undefined> undefined, gauge_label_threshold: 0, gauge_enforceMinMax: false, gauge_min: 0, diff --git a/src/config/Options/shape/pie.ts b/src/config/Options/shape/pie.ts index 31c06dbcc..296d79d4e 100644 --- a/src/config/Options/shape/pie.ts +++ b/src/config/Options/shape/pie.ts @@ -14,8 +14,8 @@ export default { * @property {object} pie Pie object * @property {boolean} [pie.label.show=true] Show or hide label on each pie piece. * @property {Function} [pie.label.format] Set formatter for the label on each pie piece. - * @property {number} [pie.label.threshold=0.05] Set threshold ratio to show/hide labels. * @property {number|Function} [pie.label.ratio=undefined] Set ratio of labels position. + * @property {number} [pie.label.threshold=0.05] Set threshold ratio to show/hide labels. * @property {boolean|object} [pie.expand=true] Enable or disable expanding pie pieces. * @property {number} [pie.expand.rate=0.98] Set expand rate. * @property {number} [pie.expand.duration=50] Set expand transition time in ms. @@ -86,8 +86,8 @@ export default { */ pie_label_show: true, pie_label_format: <(() => number|string)|undefined> undefined, - pie_label_threshold: 0.05, pie_label_ratio: <(() => number)|undefined> undefined, + pie_label_threshold: 0.05, pie_expand: {}, pie_expand_rate: 0.98, pie_expand_duration: 50, diff --git a/test/shape/gauge-spec.ts b/test/shape/gauge-spec.ts index 277898741..b81d1efcf 100644 --- a/test/shape/gauge-spec.ts +++ b/test/shape/gauge-spec.ts @@ -950,4 +950,82 @@ describe("SHAPE GAUGE", () => { } }); }); + + describe("gauge label", () => { + type TPos = [number,number][]; + let args: any = { + data: { + columns: [ + ["data1", 100], + ["data2", 70], + ["data3", 30] + ], + type: "gauge", + order: "desc" + }, + legend: { + show: false + }, + gauge: { + width: 150 + } + }; + let chart; + let pos:TPos; + + beforeEach(() => { + chart = util.generate(args); + }); + + function getLabelPos(ctx): TPos { + const currPos: TPos = []; + + ctx.$.text.texts.each(function(v) { + const pos = this.getAttribute("transform").split(",").map(util.parseNum); + + currPos.push(pos); + }); + + return currPos; + } + + it("should ratio applied correctly?", () => { + pos = getLabelPos(chart); + + // update label ratio + chart.config("gauge.label.ratio", 1, true); + + const newPos = getLabelPos(chart); + + pos.forEach((v, i) => { + const [x, y] = v.map(Math.abs); + const [nx, ny] = newPos[i].map(Math.abs); + + expect(x > nx && y > ny).to.be.true; + }); + }); + + it("set options: gauge.label.ratio", () => { + args.gauge.label = { + ratio: function(d, radius, h) { + return d.value > 90 ? 1.2 : 1; + } + }; + }); + + it("should ratio applied correctly?", () => { + const newPos = getLabelPos(chart); + + pos.forEach((v, i) => { + const [x, y] = v.map(Math.abs); + const [nx, ny] = newPos[i].map(Math.abs); + + if (i === 0) { + expect(x < nx && y < ny).to.be.true; + } else { + expect(x > nx && y > ny).to.be.true; + } + }); + }); + }); }); diff --git a/types/options.shape.d.ts b/types/options.shape.d.ts index 351bd2dfb..63fa5ba61 100644 --- a/types/options.shape.d.ts +++ b/types/options.shape.d.ts @@ -341,6 +341,11 @@ export interface GaugeOptions { */ extents?(this: Chart, value: number, isMax: boolean): string | number; + /** + * Set ratio of labels position. + */ + ratio?: ((this: Chart, d: DataItem, radius: number, h: number) => void) | number + /** * Set threshold ratio to show/hide labels. */