diff --git a/common/changes/@visactor/vchart/fix-legends-layout-width_2025-10-28-06-30.json b/common/changes/@visactor/vchart/fix-legends-layout-width_2025-10-28-06-30.json new file mode 100644 index 0000000000..926b6f9ffc --- /dev/null +++ b/common/changes/@visactor/vchart/fix-legends-layout-width_2025-10-28-06-30.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: fix issue of legends label layout when resize\n\n", + "type": "none", + "packageName": "@visactor/vchart" + } + ], + "packageName": "@visactor/vchart", + "email": "lixuef1313@163.com" +} diff --git a/packages/vchart/src/component/legend/discrete/util.ts b/packages/vchart/src/component/legend/discrete/util.ts index 356915e104..e761324b52 100644 --- a/packages/vchart/src/component/legend/discrete/util.ts +++ b/packages/vchart/src/component/legend/discrete/util.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { isEmpty, isValid } from '@visactor/vutils'; +import { cloneDeep, isEmpty, isValid } from '@visactor/vutils'; import { isPercent } from '../../../util/space'; import { mergeSpec } from '@visactor/vutils-extension'; import { transformComponentStyle, transformToGraphic } from '../../../util/style'; @@ -9,12 +9,10 @@ import type { ILayoutRect } from '../../../typings/layout'; export function getLegendAttributes(spec: IDiscreteLegendSpec, rect: ILayoutRect) { const { - // 需要进行样式转换的属性 - title = {}, - item = {}, - pager = {}, - background = {}, - + title: titleSpec = {}, + item: itemSpec = {}, + pager: pagerSpec = {}, + background: backgroundSpec = {}, // 以下不属于 legend 需要的属性,单独拿出来以免污染传递给组件的属性 type, id, @@ -32,6 +30,19 @@ export function getLegendAttributes(spec: IDiscreteLegendSpec, rect: ILayoutRect ...restSpec } = spec; + let { + // 需要进行样式转换的属性 + title = {}, + item = {}, + pager = {}, + background = {} + } = spec; + // 需要进行深拷贝,否则会影响到 spec 中的原始数据 + title = cloneDeep(title); + item = cloneDeep(item); + pager = cloneDeep(pager); + background = cloneDeep(background); + const attrs: any = restSpec; // transform title diff --git a/packages/vchart/src/layout/base-layout.ts b/packages/vchart/src/layout/base-layout.ts index 2229b38e75..64a8a7cb08 100644 --- a/packages/vchart/src/layout/base-layout.ts +++ b/packages/vchart/src/layout/base-layout.ts @@ -113,6 +113,7 @@ export class Layout implements IBaseLayout { recomputeWidth: this.recomputeWidth, recomputeHeight: this.recomputeHeight }; + const secondLayoutLeftRight = _chart?.getSpec()?.layout?.secondLayoutLeftRight ?? false; // 先布局 normal 类型的元素 this._layoutNormalItems(items, recompute); // 开始布局 region 相关元素 @@ -127,7 +128,14 @@ export class Layout implements IBaseLayout { // 有元素开启了自动缩进 // TODO:目前只有普通占位布局下的 region-relative 元素支持 // 主要考虑常规元素超出画布一般为用户个性设置,而且可以设置padding规避裁剪,不需要使用自动缩进 - this.layoutRegionItems(regionItems, relativeItems, relativeOverlapItems, overlapItems, recompute); + this.layoutRegionItems( + regionItems, + relativeItems, + relativeOverlapItems, + overlapItems, + recompute, + secondLayoutLeftRight + ); // 缩进 this._processAutoIndent( regionItems, @@ -136,7 +144,8 @@ export class Layout implements IBaseLayout { overlapItems, allRelatives, layoutTemp, - recompute + recompute, + secondLayoutLeftRight ); this.layoutAbsoluteItems(items.filter(x => x.layoutType === 'absolute')); @@ -162,7 +171,8 @@ export class Layout implements IBaseLayout { }, allRelatives: ILayoutItem[], layoutTemp: LayoutSideType, - recompute: IRecompute + recompute: IRecompute, + secondLayoutLeftRight: boolean = false ): void { // 如果有缩进 if (allRelatives.some(i => i.autoIndent)) { @@ -176,7 +186,14 @@ export class Layout implements IBaseLayout { this.leftCurrent = layoutTemp.left + left; this.rightCurrent = layoutTemp.right - right; // reLayout - this.layoutRegionItems(regionItems, relativeItems, relativeOverlapItems, overlapItems, recompute); + this.layoutRegionItems( + regionItems, + relativeItems, + relativeOverlapItems, + overlapItems, + recompute, + secondLayoutLeftRight + ); } } } @@ -362,8 +379,12 @@ export class Layout implements IBaseLayout { bottom: { items: [], rect: { width: 0, height: 0 } }, z: { items: [], rect: { width: 0, height: 0 } } }, - recompute: IRecompute + recompute: IRecompute, + secondLayoutLeftRight: boolean = false ): void { + const leftBeforeLayout = this.leftCurrent; + const rightBeforeLayout = this.rightCurrent; + let regionRelativeTotalWidth = this.rightCurrent - this.leftCurrent; let regionRelativeTotalHeight = this.bottomCurrent - this.topCurrent; @@ -376,6 +397,7 @@ export class Layout implements IBaseLayout { this._layoutRelativeOverlap('left', overlapItems.left, recompute); this._layoutRelativeOverlap('right', overlapItems.right, recompute); + // 此时得到宽度 regionRelativeTotalWidth = this.rightCurrent - this.leftCurrent; regionRelativeItems @@ -390,6 +412,21 @@ export class Layout implements IBaseLayout { // 此时得到height regionRelativeTotalHeight = this.bottomCurrent - this.topCurrent; + if (secondLayoutLeftRight) { + /** 多次布局保证不被裁减 */ + // 使用高度再次布局一次 + this.leftCurrent = leftBeforeLayout; + this.rightCurrent = rightBeforeLayout; + regionRelativeItems + .filter(x => x.layoutOrient === 'left' || x.layoutOrient === 'right') + .forEach(item => { + this._layoutRelativeItem(item, recompute); + }); + + // 此时得到宽度 + regionRelativeTotalWidth = this.rightCurrent - this.leftCurrent; + } + // region 处理 const { regionWidth, regionHeight } = this._layoutRegionItem( regionItems, diff --git a/packages/vchart/src/layout/interface.ts b/packages/vchart/src/layout/interface.ts index eda147d9c1..0b350c5692 100644 --- a/packages/vchart/src/layout/interface.ts +++ b/packages/vchart/src/layout/interface.ts @@ -119,6 +119,11 @@ export interface IBaseLayoutSpec extends ILayoutSpecBase { * 设置布局类型为默认布局 */ type: 'base'; + /** + * 是否在第一次布局完成后,再次布局一次,用于解决第一次布局时,元素宽度或高度为0的问题 + * @since 2.0.7 + */ + secondLayoutLeftRight?: boolean; } export type ILayoutSpec = IBaseLayoutSpec | IGridLayoutSpec;