Skip to content

Commit

Permalink
fix: 列头text未适配left/right对齐方式
Browse files Browse the repository at this point in the history
  • Loading branch information
lcx-seima committed Jul 1, 2022
1 parent cbe8833 commit cad4ed7
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 53 deletions.
95 changes: 64 additions & 31 deletions packages/s2-core/src/cell/col-cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ import { HeaderCell } from './header-cell';
export class ColCell extends HeaderCell {
protected declare headerConfig: ColHeaderConfig;

/** 文字区域(含icon)绘制起始坐标 */
protected textAreaPosition: Point;
/** 文字绘制起始坐标 */
protected textPosition: Point;

public get cellType() {
return CellTypes.COL_CELL;
Expand Down Expand Up @@ -107,24 +107,60 @@ export class ColCell extends HeaderCell {
}

protected getIconPosition(): Point {
const { isLeaf } = this.meta;
const iconStyle = this.getIconStyle();

if (isLeaf) {
if (this.meta.isLeaf) {
return super.getIconPosition(this.getActionIconsCount());
}

const position = this.textAreaPosition;
// 非叶子节点,因 label 滚动展示,需要适配不同 align情况
const iconStyle = this.getIconStyle();
const iconMarginLeft = iconStyle.margin.left;

const totalSpace =
this.actualTextWidth +
this.getActionIconsWidth() -
iconStyle.margin.right;
const startX = position.x - totalSpace / 2;
const textStyle = this.getTextStyle();
const position = this.textPosition;
const textX = position.x;

const y = position.y - iconStyle.size / 2;

if (textStyle.textAlign === 'left') {
/**
* textX x
* | |
* v v
* +---------+ +----+
* | text |--|icon|
* +---------+ +----+
*/
return {
x: textX + this.actualTextWidth + iconMarginLeft,
y,
};
}
if (textStyle.textAlign === 'right') {
/**
* textX x
* | |
* v v
* +---------+ +----+
* | text |--|icon|
* +---------+ +----+
*/
return {
x: textX + iconMarginLeft,
y,
};
}

/**
* textX x
* | |
* v v
* +---------+ +----+
* | text |--|icon|
* +---------+ +----+
*/
return {
x: startX + this.actualTextWidth + iconStyle.margin.left,
y: position.y - iconStyle.size / 2,
x: textX + this.actualTextWidth / 2 + iconMarginLeft,
y,
};
}

Expand Down Expand Up @@ -173,38 +209,35 @@ export class ColCell extends HeaderCell {
this.getStyle().cell?.padding,
);

const iconCount = this.getActionIconsCount();
const textAndIconSpace =
this.actualTextWidth +
this.getActionIconsWidth() -
(iconCount ? iconStyle.margin.right : 0);
const actionIconSpace = this.getActionIconsWidth();
const textAndIconSpace = this.actualTextWidth + actionIconSpace;

const textAreaRange = getTextAreaRange(
adjustedViewport,
{ start: contentBox.x, width: contentBox.width },
textAndIconSpace, // icon position 默认为 right
);

// textAreaRange.start 是以文字样式为 center 计算出的文字绘制点
// 此处按实际样式(left or right)调整
const startX = adjustColHeaderScrollingTextPosition(
textAreaRange.start,
textAreaRange.width - textAndIconSpace,
// textAreaRange.start 是 text&icon 整个区域的 center
// 此处按实际样式(left or right)调整计算出的文字绘制点
const textX = adjustColHeaderScrollingTextPosition(
textAreaRange,
this.actualTextWidth,
actionIconSpace,
textAlign,
);

const textY = contentBox.y + contentBox.height / 2;
this.textAreaPosition = { x: startX, y: textY };
return {
x: startX - textAndIconSpace / 2 + this.actualTextWidth / 2,
y: textY,
};

this.textPosition = { x: textX, y: textY };
return this.textPosition;
}

protected getActionIconsWidth() {
const { size, margin } = this.getStyle().icon;
const iconCount = this.getActionIconsCount();
return (size + margin.left) * iconCount + iconCount > 0 ? margin.right : 0;
return (
(size + margin.left) * iconCount + (iconCount > 0 ? margin.right : 0)
);
}

protected getColResizeAreaKey() {
Expand Down
66 changes: 44 additions & 22 deletions packages/s2-core/src/utils/cell/cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,14 @@ export const getTextPosition = (
) => getTextAndFollowingIconPosition(contentBox, textCfg).text;

/**
* 在给定视窗和单元格的情况下,计算单元格文字实际绘制位置
* 在给定视窗和单元格的情况下,计算单元格文字区域的坐标信息
* 计算遵循原则:
* 1. 若可视范围小,尽可能多展示文字
* 2. 若可视范围大,居中展示文字
* @param viewport 视窗坐标信息
* @param content content 列头单元格 content 区域坐标信息
* @param textWidth 文字实际绘制区域宽度(含icon)
* @returns 文字绘制位置
* @returns 文字绘制位置(start 为文字区域的中点坐标值)
*/
export const getTextAreaRange = (
viewport: AreaRange,
Expand Down Expand Up @@ -333,7 +333,7 @@ export const getBorderPositionAndStyle = (
*
* 以 textAlign=left 情况为例,由大到小的矩形分别是 viewport、cellContent、cellText
* 左图是未调整前,滚动相交判定在 viewport 最左侧,即 colCell 滚动到 viewport 左侧后,文字会贴左边绘制
* 右图是调整后,range.start 提前了 padding.left 个元素,文字与 viewport 有一定间隙更加美观
* 右图是调整后,range.start 提前了 padding.left 个像素,文字与 viewport 有一定间隙更加美观
*
* range.start range.start
* | |
Expand Down Expand Up @@ -375,29 +375,51 @@ export const adjustColHeaderScrollingViewport = (
};

/**
* 根据文字样式调整绘制的起始点(底层g始终使用 center 样式绘制)
* @param startX
* @param restWidth
* @param textAlign
* @returns
* 根据文字样式计算文字实际绘制起始
*
* 以 textAlign=left 为例,g 绘制时取 text 最左侧的坐标值作为基准坐标
*
* 计算前: 计算后:
* startX = textAreaRange.start = 中心点 startX = 最左侧坐标
*
* textAreaRange.start startX
* | |
* v v
* +----------------------------+ +----------------------------+
* | +------------------+ | |+------------------+ |
* | | text | icon | | || text | icon | |
* | +------------------+ | |+------------------+ |
* +----------------------------+ +----------------------------+
* <------------------>
* textAndIconSpace
* <---------------------------->
* textAreaRange.width
*
* @param textAreaRange 文本&icon 绘制坐标
* @param actualTextWidth 文本实际宽度
* @param actionIconSpace icon 区域实际宽度
* @param textAlign 对齐样式
* @returns 文字绘制起点坐标
*/
export const adjustColHeaderScrollingTextPosition = (
startX: number,
restWidth: number,
textAreaRange: AreaRange,
actualTextWidth: number,
actionIconSpace: number,
textAlign: TextAlign,
) => {
if (restWidth <= 0) {
// 没有足够的空间用于调整
return startX;
}
const textAndIconSpace = actualTextWidth + actionIconSpace;
const startX = textAreaRange.start; // 文本&icon 区域中心点坐标 x

switch (textAlign) {
case 'left':
return startX - restWidth / 2;
case 'right':
return startX + restWidth / 2;
case 'center':
default:
return startX;
if (textAlign === 'center') {
return startX - actionIconSpace / 2;
}

const hasEnoughWidth = textAreaRange.width - textAndIconSpace > 0;
const offset = hasEnoughWidth
? textAreaRange.width / 2
: textAndIconSpace / 2;

return textAlign === 'left'
? startX - offset
: startX + offset - actionIconSpace;
};

0 comments on commit cad4ed7

Please sign in to comment.