diff --git a/__tests__/bugs/issue-2021-spec.ts b/__tests__/bugs/issue-2021-spec.ts index c62c03b9ad..eb34acbe95 100644 --- a/__tests__/bugs/issue-2021-spec.ts +++ b/__tests__/bugs/issue-2021-spec.ts @@ -2,28 +2,7 @@ import { TinyLine, TinyArea, TinyColumn } from '../../src'; import { createDiv } from '../utils/dom'; const DATA = [ - 264, - 417, - 438, - 887, - 309, - 397, - 550, - 575, - 563, - 430, - 525, - 592, - 492, - 467, - 513, - 546, - 983, - 340, - 539, - 243, - 226, - 192, + 264, 417, 438, 887, 309, 397, 550, 575, 563, 430, 525, 592, 492, 467, 513, 546, 983, 340, 539, 243, 226, 192, ]; describe('#2021', () => { diff --git a/__tests__/unit/plots/bullet/change-data-spec.ts b/__tests__/unit/plots/bullet/change-data-spec.ts index 2247a4723a..75f3a9c281 100644 --- a/__tests__/unit/plots/bullet/change-data-spec.ts +++ b/__tests__/unit/plots/bullet/change-data-spec.ts @@ -30,7 +30,11 @@ describe('Bullet changeData', () => { const newData = [{ title: '数学', ranges: [0, 50, 100], measures: [120], target: 85 }]; bullet.changeData(newData); - const { min: newMin, max: newMax, ds: newDs } = transformData({ + const { + min: newMin, + max: newMax, + ds: newDs, + } = transformData({ data: newData, measureField: 'measures', rangeField: 'ranges', @@ -61,7 +65,11 @@ describe('Bullet changeData', () => { expect(bullet.chart.geometries[0].data).toEqual([]); bullet.changeData(bulletData); - const { min: newMin, max: newMax, ds: newDs } = transformData({ + const { + min: newMin, + max: newMax, + ds: newDs, + } = transformData({ data: bulletData, measureField: 'measures', rangeField: 'ranges', diff --git a/__tests__/unit/plots/sankey/layout-spec.ts b/__tests__/unit/plots/sankey/layout-spec.ts index 0accb9c495..8006554e34 100644 --- a/__tests__/unit/plots/sankey/layout-spec.ts +++ b/__tests__/unit/plots/sankey/layout-spec.ts @@ -35,20 +35,14 @@ describe('sankeyLayout', () => { expect(data.nodes[0].name).toBe("Agricultural 'waste'"); expect(data.nodes[0].x).toEqual([0, 0.008, 0.008, 0]); expect(data.nodes[0].y).toEqual([ - 0.15714829392583463, - 0.15714829392583463, - 0.17602864502202453, - 0.17602864502202453, + 0.15714829392583463, 0.15714829392583463, 0.17602864502202453, 0.17602864502202453, ]); expect(data.links[0].source.name).toBe("Agricultural 'waste'"); expect(data.links[0].target.name).toBe('Bio-conversion'); expect(data.links[0].x).toEqual([0.008, 0.008, 0.1417142857142857, 0.1417142857142857]); expect(data.links[0].y).toEqual([ - 0.17602864502202453, - 0.15714829392583463, - 0.23174113600532192, - 0.21286078490913202, + 0.17602864502202453, 0.15714829392583463, 0.23174113600532192, 0.21286078490913202, ]); }); }); diff --git a/docs/common/bar-style.en.md b/docs/common/bar-style.en.md index bec1c52b25..ceda2a414e 100644 --- a/docs/common/bar-style.en.md +++ b/docs/common/bar-style.en.md @@ -1,3 +1,19 @@ +#### intervalPadding + +**optional**, _number_ + +Specify the padding of interval, pixel value. Used in GroupColumn plot. + + + +#### dodgePadding + +**optional**, _number_ + +Specify the padding of interval on the same group, pixel value. Used in GroupColumn plot. + + + #### minBarWidth **optional**, _number_ diff --git a/docs/common/bar-style.zh.md b/docs/common/bar-style.zh.md index 8f25ce3fb6..6897fa014f 100644 --- a/docs/common/bar-style.zh.md +++ b/docs/common/bar-style.zh.md @@ -1,3 +1,18 @@ +#### intervalPadding + +**可选**, _number_ + +功能描述: 分组柱状图的组间间距调整,像素级别。 + + + +#### dodgePadding + +**可选**, _number_ + +功能描述: 分组柱状图的组内柱子间距调整,像素级别。 + + #### minBarWidth diff --git a/docs/common/column-style.en.md b/docs/common/column-style.en.md index 13ae68de2f..628e3f6c51 100644 --- a/docs/common/column-style.en.md +++ b/docs/common/column-style.en.md @@ -1,3 +1,19 @@ +#### intervalPadding + +**optional**, _number_ + +Specify the padding of interval, pixel value. Used in GroupColumn plot. + + + +#### dodgePadding + +**optional**, _number_ + +Specify the padding of interval on the same group, pixel value. Used in GroupColumn plot. + + + #### minColumnWidth **optional**, _number_ diff --git a/docs/common/column-style.zh.md b/docs/common/column-style.zh.md index 3f4c596aab..a8de6a371d 100644 --- a/docs/common/column-style.zh.md +++ b/docs/common/column-style.zh.md @@ -1,3 +1,18 @@ +#### intervalPadding + +**可选**, _number_ + +功能描述: 分组柱状图的组间间距调整,像素级别。 + + + +#### dodgePadding + +**可选**, _number_ + +功能描述: 分组柱状图的组内柱子间距调整,像素级别。 + + #### minColumnWidth diff --git a/examples/bar/grouped/demo/dodge-padding.ts b/examples/bar/grouped/demo/dodge-padding.ts new file mode 100644 index 0000000000..70b46862df --- /dev/null +++ b/examples/bar/grouped/demo/dodge-padding.ts @@ -0,0 +1,78 @@ +import { Bar } from '@antv/g2plot'; + +const data = [ + { + label: 'Mon.', + type: 'series1', + value: 2800, + }, + { + label: 'Mon.', + type: 'series2', + value: 2260, + }, + { + label: 'Tues.', + type: 'series1', + value: 1800, + }, + { + label: 'Tues.', + type: 'series2', + value: 1300, + }, + { + label: 'Wed.', + type: 'series1', + value: 950, + }, + { + label: 'Wed.', + type: 'series2', + value: 900, + }, + { + label: 'Thur.', + type: 'series1', + value: 500, + }, + { + label: 'Thur.', + type: 'series2', + value: 390, + }, + { + label: 'Fri.', + type: 'series1', + value: 170, + }, + { + label: 'Fri.', + type: 'series2', + value: 100, + }, +]; + +const stackedBarPlot = new Bar('container', { + data, + isGroup: true, + xField: 'value', + yField: 'label', + seriesField: 'type', + dodgePadding: 4, + label: { + // 可手动配置 label 数据标签位置 + position: 'middle', // 'left', 'middle', 'right' + // 可配置附加的布局方法 + layout: [ + // 柱形图数据标签位置自动调整 + { type: 'interval-adjust-position' }, + // 数据标签防遮挡 + { type: 'interval-hide-overlap' }, + // 数据标签文颜色自动调整 + { type: 'adjust-color' }, + ], + }, +}); + +stackedBarPlot.render(); diff --git a/examples/bar/grouped/demo/interval-padding.ts b/examples/bar/grouped/demo/interval-padding.ts new file mode 100644 index 0000000000..eeeb5cbca3 --- /dev/null +++ b/examples/bar/grouped/demo/interval-padding.ts @@ -0,0 +1,79 @@ +import { Bar } from '@antv/g2plot'; + +const data = [ + { + label: 'Mon.', + type: 'series1', + value: 2800, + }, + { + label: 'Mon.', + type: 'series2', + value: 2260, + }, + { + label: 'Tues.', + type: 'series1', + value: 1800, + }, + { + label: 'Tues.', + type: 'series2', + value: 1300, + }, + { + label: 'Wed.', + type: 'series1', + value: 950, + }, + { + label: 'Wed.', + type: 'series2', + value: 900, + }, + { + label: 'Thur.', + type: 'series1', + value: 500, + }, + { + label: 'Thur.', + type: 'series2', + value: 390, + }, + { + label: 'Fri.', + type: 'series1', + value: 170, + }, + { + label: 'Fri.', + type: 'series2', + value: 100, + }, +]; + +const stackedBarPlot = new Bar('container', { + data, + isGroup: true, + xField: 'value', + yField: 'label', + seriesField: 'type', + dodgePadding: 4, + intervalPadding: 20, + label: { + // 可手动配置 label 数据标签位置 + position: 'middle', // 'left', 'middle', 'right' + // 可配置附加的布局方法 + layout: [ + // 柱形图数据标签位置自动调整 + { type: 'interval-adjust-position' }, + // 数据标签防遮挡 + { type: 'interval-hide-overlap' }, + // 数据标签文颜色自动调整 + { type: 'adjust-color' }, + ], + }, +}); + +stackedBarPlot.render(); diff --git a/examples/bar/grouped/demo/meta.json b/examples/bar/grouped/demo/meta.json index 233e806c21..a77d4d89b4 100644 --- a/examples/bar/grouped/demo/meta.json +++ b/examples/bar/grouped/demo/meta.json @@ -19,6 +19,22 @@ "en": "Bar plot with corner-radius" }, "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/vFQNz1dCaD/21d77486-a9a3-4287-bc49-24fc40ad4800.png" + }, + { + "filename": "dodge-padding.ts", + "title": { + "zh": "分组条形图像素级组内柱子间距", + "en": "DodgePadding of grouped bar plot" + }, + "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/pb4RmT767Q/953ed207-ec9b-4d0b-8f19-dadd7e016610.png" + }, + { + "filename": "interval-padding.ts", + "title": { + "zh": "分组条形图像素级组间间距", + "en": "IntervalPadding of grouped bar plot" + }, + "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/%24aj8gaJ%267H/8d4e1840-3aa0-44af-bae4-6f6aa4de47e0.png" } ] } diff --git a/examples/column/grouped/demo/dodge-padding.ts b/examples/column/grouped/demo/dodge-padding.ts new file mode 100644 index 0000000000..416c31e82b --- /dev/null +++ b/examples/column/grouped/demo/dodge-padding.ts @@ -0,0 +1,30 @@ +import { Column } from '@antv/g2plot'; + +fetch('https://gw.alipayobjects.com/os/antfincdn/iPY8JFnxdb/dodge-padding.json') + .then((data) => data.json()) + .then((data) => { + const plot = new Column('container', { + data, + isGroup: true, + xField: '月份', + yField: '月均降雨量', + seriesField: 'name', + // 分组柱状图 组内柱子间的间距 (像素级别) + dodgePadding: 2, + label: { + // 可手动配置 label 数据标签位置 + position: 'middle', // 'top', 'middle', 'bottom' + // 可配置附加的布局方法 + layout: [ + // 柱形图数据标签位置自动调整 + { type: 'interval-adjust-position' }, + // 数据标签防遮挡 + { type: 'interval-hide-overlap' }, + // 数据标签文颜色自动调整 + { type: 'adjust-color' }, + ], + }, + }); + + plot.render(); + }); diff --git a/examples/column/grouped/demo/interval-padding.ts b/examples/column/grouped/demo/interval-padding.ts new file mode 100644 index 0000000000..b79bce1a39 --- /dev/null +++ b/examples/column/grouped/demo/interval-padding.ts @@ -0,0 +1,32 @@ +import { Column } from '@antv/g2plot'; + +fetch('https://gw.alipayobjects.com/os/antfincdn/iPY8JFnxdb/dodge-padding.json') + .then((data) => data.json()) + .then((data) => { + const plot = new Column('container', { + data, + isGroup: true, + xField: '月份', + yField: '月均降雨量', + seriesField: 'name', + // 分组柱状图 组内柱子间的间距 (像素级别) + dodgePadding: 2, + // 分组柱状图 组间的间距 (像素级别) + intervalPadding: 20, + label: { + // 可手动配置 label 数据标签位置 + position: 'middle', // 'top', 'middle', 'bottom' + // 可配置附加的布局方法 + layout: [ + // 柱形图数据标签位置自动调整 + { type: 'interval-adjust-position' }, + // 数据标签防遮挡 + { type: 'interval-hide-overlap' }, + // 数据标签文颜色自动调整 + { type: 'adjust-color' }, + ], + }, + }); + + plot.render(); + }); diff --git a/examples/column/grouped/demo/meta.json b/examples/column/grouped/demo/meta.json index 14082d3253..910f52a0fe 100644 --- a/examples/column/grouped/demo/meta.json +++ b/examples/column/grouped/demo/meta.json @@ -35,6 +35,22 @@ "en": "Stacked grouped column plot" }, "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/9ExrwrpVrA/908eff62-1132-4dbb-8c3c-9cbe8183c6d8.png" + }, + { + "filename": "dodge-padding.ts", + "title": { + "zh": "分组柱状图像素级组内柱子间距", + "en": "DodgePadding of grouped column plot" + }, + "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/VL8xZlzwm5/2d96f1be-83c6-47c8-8a02-6023ecdbe035.png" + }, + { + "filename": "interval-padding.ts", + "title": { + "zh": "分组柱状图像素级组间间距", + "en": "IntervalPadding of grouped column plot" + }, + "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/lRokVhHkrr/61d333f8-9d15-4327-b70f-8e026453cf70.png" } ] } diff --git a/src/adaptor/geometries/base.ts b/src/adaptor/geometries/base.ts index 2b0ccf316a..d9090226fc 100644 --- a/src/adaptor/geometries/base.ts +++ b/src/adaptor/geometries/base.ts @@ -122,19 +122,8 @@ export function getMappingFunction(mappingFields: string[], func: (datum: Datum) */ export function geometry(params: Params): Params { const { chart, options } = params; - const { - type, - args, - mapping, - xField, - yField, - colorField, - shapeField, - sizeField, - tooltipFields, - label, - state, - } = options; + const { type, args, mapping, xField, yField, colorField, shapeField, sizeField, tooltipFields, label, state } = + options; // 如果没有 mapping 信息,那么直接返回 if (!mapping) { diff --git a/src/adaptor/geometries/interval.ts b/src/adaptor/geometries/interval.ts index fef136feb5..e816309fc8 100644 --- a/src/adaptor/geometries/interval.ts +++ b/src/adaptor/geometries/interval.ts @@ -18,8 +18,12 @@ export interface IntervalGeometryOptions extends GeometryOptions { readonly isStack?: boolean; /** 柱状图宽度占比 [0-1] */ readonly widthRatio?: number; + /** 分组间柱子之间的组间间距(像素级),仅对分组柱状图适用 */ + readonly intervalPadding?: number; /** 分组中柱子之间的间距 [0-1],仅对分组柱状图适用 */ readonly marginRatio?: number; + /** 分组中柱子之间的组内间距(像素级),仅对分组柱状图适用 */ + readonly dodgePadding?: number; /** 柱状图最小宽度(像素) */ readonly minColumnWidth?: number; /** 柱状图最大宽度(像素) */ @@ -82,7 +86,18 @@ function otherAdaptor(params: Params): Par export function interval(params: Params): Params { const { options } = params; - const { xField, yField, interval, seriesField, tooltip, minColumnWidth, maxColumnWidth, columnBackground } = options; + const { + xField, + yField, + interval, + seriesField, + tooltip, + minColumnWidth, + maxColumnWidth, + columnBackground, + dodgePadding, + intervalPadding, + } = options; const { fields, formatter } = getTooltipMapping(tooltip, [xField, yField, seriesField]); @@ -98,7 +113,7 @@ export function interval(params: Params): tooltip: formatter, ...interval, }, - args: { minColumnWidth, maxColumnWidth, background: columnBackground }, + args: { dodgePadding, intervalPadding, minColumnWidth, maxColumnWidth, background: columnBackground }, }, }) ) diff --git a/src/plots/column/types.ts b/src/plots/column/types.ts index 91fc83345d..9165bce854 100644 --- a/src/plots/column/types.ts +++ b/src/plots/column/types.ts @@ -2,8 +2,15 @@ import { ShapeAttrs } from '@antv/g2'; import { Options, StyleAttr } from '../../types'; import { OptionWithConversionTag } from '../../adaptor/conversion-tag'; import { OptionWithConnectedArea } from '../../adaptor/connected-area'; +import { IntervalGeometryOptions } from '../../adaptor/geometries/interval'; -export interface ColumnOptions extends Options, OptionWithConversionTag, OptionWithConnectedArea { +type PartialIntervalGeometryOptions = Pick; + +export interface ColumnOptions + extends Options, + OptionWithConversionTag, + OptionWithConnectedArea, + PartialIntervalGeometryOptions { /** x 轴字段 */ readonly xField: string; /** y 轴字段 */ diff --git a/src/plots/sankey/sankey/sankey.ts b/src/plots/sankey/sankey/sankey.ts index 38d5b48846..de9359102c 100644 --- a/src/plots/sankey/sankey/sankey.ts +++ b/src/plots/sankey/sankey/sankey.ts @@ -241,7 +241,7 @@ export function Sankey() { } function initializeNodeBreadths(columns) { - const ky = (minValueBy(columns, (c: any[]) => (y1 - y0 - (c.length - 1) * py) / sumBy(c, value)) as any) as number; + const ky = minValueBy(columns, (c: any[]) => (y1 - y0 - (c.length - 1) * py) / sumBy(c, value)) as any as number; for (const nodes of columns) { let y = y0; for (const node of nodes) { @@ -264,7 +264,7 @@ export function Sankey() { function computeNodeBreadths(graph) { const columns = computeNodeLayers(graph); - py = Math.min(dy, (y1 - y0) / (((maxValueBy(columns, (c: any[]) => c.length) as any) as number) - 1)); + py = Math.min(dy, (y1 - y0) / ((maxValueBy(columns, (c: any[]) => c.length) as any as number) - 1)); initializeNodeBreadths(columns); for (let i = 0; i < iterations; ++i) { const alpha = Math.pow(0.99, i); diff --git a/src/plots/waterfall/adaptor.ts b/src/plots/waterfall/adaptor.ts index fbcc8b94e5..a69140cc62 100644 --- a/src/plots/waterfall/adaptor.ts +++ b/src/plots/waterfall/adaptor.ts @@ -16,18 +16,8 @@ import './shape'; */ function geometry(params: Params): Params { const { chart, options } = params; - const { - data, - xField, - yField, - total, - leaderLine, - columnWidthRatio, - waterfallStyle, - risingFill, - fallingFill, - color, - } = options; + const { data, xField, yField, total, leaderLine, columnWidthRatio, waterfallStyle, risingFill, fallingFill, color } = + options; // 数据处理 chart.data(transformData(data, xField, yField, total)); diff --git a/src/utils/statistic.ts b/src/utils/statistic.ts index 9e763f5645..ec796d9e2f 100644 --- a/src/utils/statistic.ts +++ b/src/utils/statistic.ts @@ -34,10 +34,12 @@ export function adapteStyle(style?: StatisticText['style']): object { if (get(style, 'fill')) { styleObject['color'] = style['fill']; } - const { shadowColor, shadowBlur = 0, shadowOffsetX = 0, shadowOffsetY = 0 } = pick( - style, - shapeStyleKeys - ) as ShapeStyle; + const { + shadowColor, + shadowBlur = 0, + shadowOffsetX = 0, + shadowOffsetY = 0, + } = pick(style, shapeStyleKeys) as ShapeStyle; styleObject['text-shadow'] = `${[shadowColor, `${shadowOffsetX}px`, `${shadowOffsetY}px`, `${shadowBlur}px`].join( ' ' )}`;