diff --git a/__tests__/integration/snapshots/static/alphabetIntervalMinHeight.png b/__tests__/integration/snapshots/static/alphabetIntervalMinHeight.png new file mode 100644 index 0000000000..412858c293 Binary files /dev/null and b/__tests__/integration/snapshots/static/alphabetIntervalMinHeight.png differ diff --git a/__tests__/integration/snapshots/static/alphabetIntervalMinHeightTransposed.png b/__tests__/integration/snapshots/static/alphabetIntervalMinHeightTransposed.png new file mode 100644 index 0000000000..32eca6bf65 Binary files /dev/null and b/__tests__/integration/snapshots/static/alphabetIntervalMinHeightTransposed.png differ diff --git a/__tests__/plots/static/alphanbet-interval-min-height-transposed.ts b/__tests__/plots/static/alphanbet-interval-min-height-transposed.ts new file mode 100644 index 0000000000..abb7a0a38d --- /dev/null +++ b/__tests__/plots/static/alphanbet-interval-min-height-transposed.ts @@ -0,0 +1,29 @@ +import { G2Spec } from '../../../src'; + +export function alphabetIntervalMinHeightTransposed(): G2Spec { + return { + type: 'interval', + coordinate: { transform: [{ type: 'transpose' }] }, + data: [ + { genre: 'Sports', sold: 0 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ], + encode: { + x: 'genre', + y: 'sold', + color: 'genre', + }, + axis: { + x: { animate: false }, + y: { animate: false }, + }, + style: { + draggable: true, + droppable: true, + minHeight: 50, + }, + }; +} diff --git a/__tests__/plots/static/alphanbet-interval-min-height.ts b/__tests__/plots/static/alphanbet-interval-min-height.ts new file mode 100644 index 0000000000..80a0219c2a --- /dev/null +++ b/__tests__/plots/static/alphanbet-interval-min-height.ts @@ -0,0 +1,28 @@ +import { G2Spec } from '../../../src'; + +export function alphabetIntervalMinHeight(): G2Spec { + return { + type: 'interval', + data: [ + { genre: 'Sports', sold: 0 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ], + encode: { + x: 'genre', + y: 'sold', + color: 'genre', + }, + axis: { + x: { animate: false }, + y: { animate: false }, + }, + style: { + draggable: true, + droppable: true, + minHeight: 50, + }, + }; +} diff --git a/__tests__/plots/static/index.ts b/__tests__/plots/static/index.ts index 17b06db9f1..27f5163e8f 100644 --- a/__tests__/plots/static/index.ts +++ b/__tests__/plots/static/index.ts @@ -4,6 +4,8 @@ export { alphabetIntervalMaxWidth } from './alphabet-interval-max-width'; export { alphabetIntervalMinWidth } from './alphabet-interval-min-width'; export { alphabetIntervalMaxWidthTransposed } from './alphabet-interval-max-width-transposed'; export { alphabetIntervalMinWidthTransposed } from './alphabet-interval-min-width-transposed'; +export { alphabetIntervalMinHeight } from './alphanbet-interval-min-height'; +export { alphabetIntervalMinHeightTransposed } from './alphanbet-interval-min-height-transposed'; export { alphabetIntervalTitle } from './alphabet-interval-title'; export { alphabetIntervalLabelOverflowHide } from './alphabet-interval-label-overflow-hide'; export { alphabetIntervalLabelContrastReverse } from './alphabet-interval-label-contrast-reverse'; diff --git a/site/docs/spec/mark/interval.zh.md b/site/docs/spec/mark/interval.zh.md index 70fd1cd930..83a7d9f929 100644 --- a/site/docs/spec/mark/interval.zh.md +++ b/site/docs/spec/mark/interval.zh.md @@ -63,6 +63,7 @@ chart.render(); | ---------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | --------- | | minWidth | 柱子的最小宽度,单位为像素 | `number` | `-Infinity` | | maxWidth | 柱子的最大宽度,单位为像素 | `number` | `Infinity` | +| minHeight | 柱子的最小高度,单位为像素 | `number` | `-Infinity` | | radius | 外层矩形的四个圆角大小 | `number` \| `Function` | 0 | | radiusTopLeft | 外层左上角的圆角 | `number` \| `Function` | 0 | | radiusTopRight | 外层右上角的圆角 | `number` \| `Function` | 0 | diff --git a/site/examples/general/interval/demo/column-minHeight.ts b/site/examples/general/interval/demo/column-minHeight.ts new file mode 100644 index 0000000000..848e77f378 --- /dev/null +++ b/site/examples/general/interval/demo/column-minHeight.ts @@ -0,0 +1,20 @@ +import { Chart } from '@antv/g2'; + +const chart = new Chart({ container: 'container' }); +chart.data([ + { genre: 'Sports', sold: 0 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, +]); + +chart + .interval() + .encode('x', 'genre') + .encode('y', 'sold') + .encode('color', 'genre') + .axis({ x: { animate: false }, y: { animate: false } }) + .style('draggable', true) + .style('droppable', true) + .style('minHeight', 50); diff --git a/src/shape/interval/color.ts b/src/shape/interval/color.ts index 016b507312..a2d6d74f8e 100644 --- a/src/shape/interval/color.ts +++ b/src/shape/interval/color.ts @@ -16,6 +16,12 @@ export type ColorOptions = { * Maximum width of each interval. */ maxWidth?: number; + + /** + * Minimum height of each interval. + */ + minHeight?: number; + [key: string]: any; }; @@ -40,6 +46,7 @@ export function rect( radiusTopRight = radius, minWidth = -Infinity, maxWidth = Infinity, + minHeight = -Infinity, ...rest } = style; if (!isPolar(coordinate) && !isHelix(coordinate)) { @@ -51,6 +58,7 @@ export function rect( // Deal with width or height is negative. const absX = width > 0 ? x : x + width; const absY = height > 0 ? y : y + height; + const absWidth = Math.abs(width); const absHeight = Math.abs(height); const finalX = absX + insetLeft; @@ -59,13 +67,15 @@ export function rect( const finalHeight = absHeight - (insetTop + insetBottom); const clampWidth = tpShape - ? finalWidth + ? clamp(finalWidth, minHeight, Infinity) : clamp(finalWidth, minWidth, maxWidth); const clampHeight = tpShape ? clamp(finalHeight, minWidth, maxWidth) - : finalHeight; - const clampX = finalX - (clampWidth - finalWidth) / 2; - const clampY = finalY - (clampHeight - finalHeight) / 2; + : clamp(finalHeight, minHeight, Infinity); + const clampX = tpShape ? finalX : finalX - (clampWidth - finalWidth) / 2; + const clampY = tpShape + ? finalY - (clampHeight - finalHeight) / 2 + : finalY - (clampHeight - finalHeight); return select(document.createElement('rect', {})) .style('x', clampX) @@ -145,6 +155,7 @@ export const Color: SC = (options, context) => { insetTop = inset, minWidth, maxWidth, + minHeight, ...rest } = style; const { color = defaultColor, opacity } = value; @@ -179,6 +190,7 @@ export const Color: SC = (options, context) => { insetTop, minWidth, maxWidth, + minHeight, }; return ( diff --git a/src/shape/interval/rect.ts b/src/shape/interval/rect.ts index f27509d185..50b2dd3a9b 100644 --- a/src/shape/interval/rect.ts +++ b/src/shape/interval/rect.ts @@ -10,6 +10,11 @@ export type RectOptions = { * Maximum width of each interval. */ maxWidth?: number; + + /** + * Minimum height of each interval. + */ + minHeight?: number; }; /**