From 669ee8427ae62154f0a8e6d37154f452fa240125 Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Tue, 17 Aug 2021 14:24:37 +0800 Subject: [PATCH 01/13] refactor: fix updateShapeAttr type define --- packages/s2-core/src/utils/g-renders.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/s2-core/src/utils/g-renders.ts b/packages/s2-core/src/utils/g-renders.ts index 2601f58f11..22041b19db 100644 --- a/packages/s2-core/src/utils/g-renders.ts +++ b/packages/s2-core/src/utils/g-renders.ts @@ -4,7 +4,7 @@ */ import { TextTheme } from '@/common/interface/theme'; import { Group, IShape, ShapeAttrs } from '@antv/g-canvas'; -import _ from 'lodash'; +import { forEach, isEmpty, set } from 'lodash'; export function renderRect(group: Group, attrs: ShapeAttrs): IShape { return group?.addShape?.('rect', { @@ -28,8 +28,8 @@ export function renderText( group: Group, extraStyle?: any, ): IShape { - if (!_.isEmpty(shapes) && group) { - _.forEach(shapes, (shape: IShape) => { + if (!isEmpty(shapes) && group) { + forEach(shapes, (shape: IShape) => { if (group.contain(shape)) group.removeChild(shape, true); }); } @@ -67,12 +67,12 @@ export function renderLine( }); } -export function updateShapeAttr( +export function updateShapeAttr( shape: IShape, - attribute: keyof ShapeAttrs, - value: ShapeAttrs[keyof ShapeAttrs], + attribute: K, + value: ShapeAttrs[K], ) { if (shape) { - _.set(shape, `attrs.${attribute}`, value); + set(shape, `attrs.${attribute}`, value); } } From 7f4725c1545395c749d775237817dea8ace7ff68 Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Tue, 17 Aug 2021 15:14:43 +0800 Subject: [PATCH 02/13] refactor: refine getCellType to getter --- packages/s2-core/src/cell/base-cell.ts | 39 +++++++++++------------ packages/s2-core/src/cell/col-cell.ts | 3 +- packages/s2-core/src/cell/corner-cell.ts | 18 +++++------ packages/s2-core/src/cell/data-cell.ts | 3 +- packages/s2-core/src/cell/merged-cells.ts | 3 +- packages/s2-core/src/cell/row-cell.ts | 3 +- 6 files changed, 31 insertions(+), 38 deletions(-) diff --git a/packages/s2-core/src/cell/base-cell.ts b/packages/s2-core/src/cell/base-cell.ts index 29301461a8..ec58416cf0 100644 --- a/packages/s2-core/src/cell/base-cell.ts +++ b/packages/s2-core/src/cell/base-cell.ts @@ -11,9 +11,6 @@ import { SpreadSheet } from '../sheet-type'; import { updateShapeAttr } from '../utils/g-renders'; export abstract class BaseCell extends Group { - // used to determine the cell type - public cellType: CellTypes; - // cell's data meta info protected meta: T; @@ -50,11 +47,6 @@ export abstract class BaseCell extends Group { this.initCell(); } - /** - * Update cell's selected state - */ - public abstract update(): void; - public getMeta(): T { return this.meta; } @@ -67,32 +59,39 @@ export abstract class BaseCell extends Group { * in case there are more params to be handled * @param options any type's rest params */ - protected handleRestOptions(...options: any) { + protected handleRestOptions(...options: unknown[]) { // default do nothing } /** - * Determine how to render this cell area + * Update cell's selected state */ - protected abstract initCell(): void; + public abstract update(): void; /** * Return the type of the cell */ - protected abstract getCellType(): CellTypes; + public abstract get cellType(): CellTypes; + + /** + * Determine how to render this cell area + */ + protected abstract initCell(): void; + + /* -------------------------------------------------------------------------- */ + /* common functions that will be used in subtype */ + /* -------------------------------------------------------------------------- */ // 根据当前state来更新cell的样式 public updateByState(stateName: InteractionStateName) { const stateStyles = get(this.theme, `${this.cellType}.cell.${stateName}`); each(stateStyles, (style, styleKey) => { - if (styleKey) { - const currentShape = findKey(SHAPE_ATTRS_MAP, (attrs) => - includes(attrs, styleKey), - ); - if (!currentShape) return; - updateShapeAttr(this[currentShape], SHAPE_STYLE_MAP[styleKey], style); - this.showShapeUnderState(currentShape); - } + const currentShape = findKey(SHAPE_ATTRS_MAP, (attrs) => + includes(attrs, styleKey), + ); + if (!currentShape) return; + updateShapeAttr(this[currentShape], SHAPE_STYLE_MAP[styleKey], style); + this.showShapeUnderState(currentShape); }); } diff --git a/packages/s2-core/src/cell/col-cell.ts b/packages/s2-core/src/cell/col-cell.ts index f69a038141..d4c1890a4f 100644 --- a/packages/s2-core/src/cell/col-cell.ts +++ b/packages/s2-core/src/cell/col-cell.ts @@ -50,7 +50,6 @@ export class ColCell extends BaseCell { } protected initCell() { - this.cellType = this.getCellType(); // 1、draw rect background this.drawRectBackground(); // 2、interactive background shape @@ -67,7 +66,7 @@ export class ColCell extends BaseCell { this.updateSelected(); } - protected getCellType() { + public get cellType() { return CellTypes.COL_CELL; } diff --git a/packages/s2-core/src/cell/corner-cell.ts b/packages/s2-core/src/cell/corner-cell.ts index 74d27f48c8..899a789805 100644 --- a/packages/s2-core/src/cell/corner-cell.ts +++ b/packages/s2-core/src/cell/corner-cell.ts @@ -1,21 +1,20 @@ +import { IGroup, IShape } from '@antv/g-canvas'; import _ from 'lodash'; -import { getEllipsisText, getTextPosition } from '../utils/text'; -import { isIPhoneX } from '../utils/is-mobile'; -import { IShape } from '@antv/g-canvas'; -import { renderText } from '../utils/g-renders'; +import { GuiIcon, Node } from '..'; import { + CellTypes, + COLOR_DEFAULT_RESIZER, EXTRA_FIELD, KEY_GROUP_CORNER_RESIZER, - COLOR_DEFAULT_RESIZER, KEY_TREE_ROWS_COLLAPSE_ALL, - CellTypes, } from '../common/constant'; import { HIT_AREA } from '../facet/header/base'; import { CornerHeaderConfig } from '../facet/header/corner'; import { ResizeInfo } from '../facet/header/interface'; -import { GuiIcon, Node } from '..'; +import { renderText } from '../utils/g-renders'; +import { isIPhoneX } from '../utils/is-mobile'; +import { getEllipsisText, getTextPosition } from '../utils/text'; import { BaseCell } from './base-cell'; -import { IGroup } from '@antv/g-canvas'; export class CornerCell extends BaseCell { protected headerConfig: CornerHeaderConfig; @@ -33,14 +32,13 @@ export class CornerCell extends BaseCell { public update() {} protected initCell() { - this.cellType = this.getCellType(); this.textShapes = []; this.drawCellRect(); this.drawCellText(); this.drawHotpot(); } - protected getCellType() { + public get cellType() { return CellTypes.CORNER_CELL; } diff --git a/packages/s2-core/src/cell/data-cell.ts b/packages/s2-core/src/cell/data-cell.ts index 98024af870..0cc0e8182b 100644 --- a/packages/s2-core/src/cell/data-cell.ts +++ b/packages/s2-core/src/cell/data-cell.ts @@ -225,7 +225,6 @@ export class DataCell extends BaseCell { } protected initCell() { - this.cellType = this.getCellType(); this.conditions = this.spreadsheet.options?.conditions; this.drawBackgroundShape(); this.drawStateShapes(); @@ -237,7 +236,7 @@ export class DataCell extends BaseCell { this.setCellsSpotlight(); } - protected getCellType() { + public get cellType() { return CellTypes.DATA_CELL; } diff --git a/packages/s2-core/src/cell/merged-cells.ts b/packages/s2-core/src/cell/merged-cells.ts index e66c73530a..3fc333a2bd 100644 --- a/packages/s2-core/src/cell/merged-cells.ts +++ b/packages/s2-core/src/cell/merged-cells.ts @@ -44,7 +44,6 @@ export class MergedCells extends BaseCell { } protected initCell() { - this.cellType = this.getCellType(); // TODO:1、条件格式支持; 2、交互态扩展; 3、合并后的单元格文字布局及文字内容(目前参考Excel合并后只保留第一个单元格子的数据) this.drawBackgroundShape(); // this.drawStateShapes(); @@ -52,7 +51,7 @@ export class MergedCells extends BaseCell { // this.update(); } - protected getCellType() { + public get cellType() { return CellTypes.MERGED_CELLS; } diff --git a/packages/s2-core/src/cell/row-cell.ts b/packages/s2-core/src/cell/row-cell.ts index 39008cd946..9b8988b702 100644 --- a/packages/s2-core/src/cell/row-cell.ts +++ b/packages/s2-core/src/cell/row-cell.ts @@ -61,7 +61,6 @@ export class RowCell extends BaseCell { } protected initCell() { - this.cellType = this.getCellType(); // 1、draw rect background this.drawBackgroundColor(); this.drawInteractiveBgShape(); @@ -77,7 +76,7 @@ export class RowCell extends BaseCell { this.drawActionIcons(); } - protected getCellType() { + public get cellType() { return CellTypes.ROW_CELL; } From 82a3b9683042a98ccfc8f67a4c530282db97b778 Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Tue, 17 Aug 2021 19:24:18 +0800 Subject: [PATCH 03/13] refactor: add header cell class --- packages/s2-core/src/cell/base-cell.ts | 40 +++++------ packages/s2-core/src/cell/col-cell.ts | 71 ++++++------------- packages/s2-core/src/cell/corner-cell.ts | 52 ++++++-------- packages/s2-core/src/cell/detail-col-cell.ts | 19 ++--- packages/s2-core/src/cell/header-cell.ts | 39 ++++++++++ packages/s2-core/src/cell/row-cell.ts | 57 ++++++--------- packages/s2-core/src/common/constant/theme.ts | 2 + packages/s2-core/src/utils/g-renders.ts | 8 +++ 8 files changed, 143 insertions(+), 145 deletions(-) create mode 100644 packages/s2-core/src/cell/header-cell.ts diff --git a/packages/s2-core/src/cell/base-cell.ts b/packages/s2-core/src/cell/base-cell.ts index ec58416cf0..364f8dc8c9 100644 --- a/packages/s2-core/src/cell/base-cell.ts +++ b/packages/s2-core/src/cell/base-cell.ts @@ -6,9 +6,13 @@ import { } from '@/common/constant'; import { InteractionStateTheme, SpreadSheetTheme } from '@/common/interface'; import { Group, IShape } from '@antv/g-canvas'; -import { each, findKey, get, includes } from 'lodash'; +import { each, findKey, get, includes, toNumber } from 'lodash'; import { SpreadSheet } from '../sheet-type'; -import { updateShapeAttr } from '../utils/g-renders'; +import { + updateFillOpacity, + updateShapeAttr, + updateStrokeOpacity, +} from '../utils/g-renders'; export abstract class BaseCell extends Group { // cell's data meta info @@ -63,11 +67,6 @@ export abstract class BaseCell extends Group { // default do nothing } - /** - * Update cell's selected state - */ - public abstract update(): void; - /** * Return the type of the cell */ @@ -78,6 +77,11 @@ export abstract class BaseCell extends Group { */ protected abstract initCell(): void; + /** + * Update cell's selected state + */ + public abstract update(): void; + /* -------------------------------------------------------------------------- */ /* common functions that will be used in subtype */ /* -------------------------------------------------------------------------- */ @@ -95,26 +99,18 @@ export abstract class BaseCell extends Group { }); } - public showShapeUnderState(currentShape: string) { - this.setFillOpacity(this[currentShape], 1); - this.setStrokeOpacity(this[currentShape], 1); + private showShapeUnderState(currentShape: string) { + updateFillOpacity(this[currentShape], 1); + updateStrokeOpacity(this[currentShape], 1); } public hideShapeUnderState() { this.stateShapes.forEach((shape: IShape) => { - this.setFillOpacity(shape, 0); - this.setStrokeOpacity(shape, 0); + updateFillOpacity(shape, 0); + updateStrokeOpacity(shape, 0); }); } - public setFillOpacity(shape: IShape, opacity: number) { - updateShapeAttr(shape, 'fillOpacity', opacity); - } - - public setStrokeOpacity(shape: IShape, opacity: number) { - updateShapeAttr(shape, 'strokeOpacity', opacity); - } - public resetOpacity() { this.setBgColorOpacity(1); } @@ -123,7 +119,7 @@ export abstract class BaseCell extends Group { opacity: InteractionStateTheme['opacity'] = this.theme.dataCell?.cell ?.outOfTheSpotlight?.opacity, ) { - updateShapeAttr(this.backgroundShape, SHAPE_STYLE_MAP.opacity, opacity); - updateShapeAttr(this.textShape, SHAPE_STYLE_MAP.opacity, opacity); + updateFillOpacity(this.backgroundShape, toNumber(opacity)); + updateFillOpacity(this.textShape, toNumber(opacity)); } } diff --git a/packages/s2-core/src/cell/col-cell.ts b/packages/s2-core/src/cell/col-cell.ts index d4c1890a4f..af1cdab3de 100644 --- a/packages/s2-core/src/cell/col-cell.ts +++ b/packages/s2-core/src/cell/col-cell.ts @@ -1,4 +1,3 @@ -import { BaseCell } from '@/cell/base-cell'; import { CellTypes, COLOR_DEFAULT_RESIZER, @@ -9,28 +8,21 @@ import { TextAlign } from '@/common/interface/theme'; import { HIT_AREA } from '@/facet/header/base'; import { ColHeaderConfig } from '@/facet/header/col'; import { ResizeInfo } from '@/facet/header/interface'; -import { Node } from '@/index'; -import { renderRect, updateShapeAttr } from '@/utils/g-renders'; +import { renderRect, renderText, updateShapeAttr } from '@/utils/g-renders'; import { getEllipsisText, getTextPosition, measureTextWidth, } from '@/utils/text'; import { IGroup } from '@antv/g-canvas'; -import _ from 'lodash'; +import { get, isEqual } from 'lodash'; +import { HeaderCell } from './header-cell'; -export class ColCell extends BaseCell { +export class ColCell extends HeaderCell { protected headerConfig: ColHeaderConfig; - // protected bottomBorderHotSpot: Set; - // TODO type define - public update() { - const selectedId = this.spreadsheet.store.get('rowColSelectedId'); - if (selectedId && _.find(selectedId, (id) => id === this.meta.id)) { - this.setActive(); - } else { - this.setInactive(); - } + public get cellType() { + return CellTypes.COL_CELL; } public setActive() { @@ -45,10 +37,6 @@ export class ColCell extends BaseCell { updateShapeAttr(this.interactiveBgShape, 'fillOpacity', 0); } - protected handleRestOptions(...options) { - this.headerConfig = options[0]; - } - protected initCell() { // 1、draw rect background this.drawRectBackground(); @@ -62,21 +50,6 @@ export class ColCell extends BaseCell { this.drawRightBorder(); // 5、draw hot-spot rect this.drawHotSpot(); - - this.updateSelected(); - } - - public get cellType() { - return CellTypes.COL_CELL; - } - - private updateSelected() { - const selectedId = this.spreadsheet.store.get('rowColSelectedId'); - if (selectedId && _.find(selectedId, (id) => id === this.meta.id)) { - this.setActive(); - } else { - this.setInactive(); - } } protected getColHotSpotKey() { @@ -124,7 +97,7 @@ export class ColCell extends BaseCell { ? iconCfg.size + iconCfg.margin.right : 0; const textStyle = isLeaf && !isTotals ? textCfg : bolderTextCfg; - const padding = _.get(this, 'theme.colCell.cell.padding'); + const padding = get(this, 'theme.colCell.cell.padding'); const text = getEllipsisText( content, cellWidth - sortIconPadding - padding?.left - padding?.right, @@ -136,8 +109,8 @@ export class ColCell extends BaseCell { let textAlign: TextAlign; if (isLeaf) { // 最后一个层级的维值,与 dataCell 对齐方式保持一致 - textAlign = _.get(this, 'theme.dataCell.text.textAlign'); - const textBaseline = _.get(this, 'theme.dataCell.text.textBaseline'); + textAlign = get(this, 'theme.dataCell.text.textAlign'); + const textBaseline = get(this, 'theme.dataCell.text.textBaseline'); textStyle.textBaseline = textBaseline; const cellBoxCfg = { x, @@ -193,7 +166,7 @@ export class ColCell extends BaseCell { } // const derivedValue = this.spreadsheet.getDerivedValue(value); // if ( - // !_.isEqual( + // !isEqual( // derivedValue.derivedValueField, // derivedValue.displayDerivedValueField, // ) && @@ -207,22 +180,24 @@ export class ColCell extends BaseCell { // if ( // key === EXTRA_FIELD && // this.spreadsheet.isDerivedValue(value) && - // _.last(derivedValue.displayDerivedValueField) === value + // last(derivedValue.displayDerivedValueField) === value // ) { // // 度量列,找到 value值 // text += '...'; // } // } - this.addShape('text', { - attrs: { - x: textX, - y: textY, - text, + this.textShape = renderText( + [this.textShape], + textX, + textY, + text, + { textAlign, ...textStyle, - cursor: 'pointer', }, - }); + this, + { cursor: 'pointer' }, + ); } // 交互使用的背景色 @@ -243,8 +218,8 @@ export class ColCell extends BaseCell { const { sortParam } = this.headerConfig; const query = this.meta.query; return ( - _.isEqual(_.get(sortParam, 'query'), query) && - _.get(sortParam, 'type') !== 'none' + isEqual(get(sortParam, 'query'), query) && + get(sortParam, 'type') !== 'none' ); } @@ -255,7 +230,7 @@ export class ColCell extends BaseCell { const { sortParam } = this.headerConfig; const { x, y, width: cellWidth, height: cellHeight } = this.meta; const iconShape = new GuiIcon({ - type: _.get(sortParam, 'type', 'none'), + type: get(sortParam, 'type', 'none'), x: x + cellWidth - icon.size - icon.margin.right, y: y + (cellHeight - icon.size) / 2, width: icon.size, diff --git a/packages/s2-core/src/cell/corner-cell.ts b/packages/s2-core/src/cell/corner-cell.ts index 899a789805..0b444862d1 100644 --- a/packages/s2-core/src/cell/corner-cell.ts +++ b/packages/s2-core/src/cell/corner-cell.ts @@ -1,6 +1,7 @@ -import { IGroup, IShape } from '@antv/g-canvas'; -import _ from 'lodash'; -import { GuiIcon, Node } from '..'; +import { renderRect } from '@/utils/g-renders'; +import { IGroup, IShape, ShapeAttrs } from '@antv/g-canvas'; +import { get, isEmpty, isEqual } from 'lodash'; +import { GuiIcon } from '..'; import { CellTypes, COLOR_DEFAULT_RESIZER, @@ -14,19 +15,14 @@ import { ResizeInfo } from '../facet/header/interface'; import { renderText } from '../utils/g-renders'; import { isIPhoneX } from '../utils/is-mobile'; import { getEllipsisText, getTextPosition } from '../utils/text'; -import { BaseCell } from './base-cell'; -export class CornerCell extends BaseCell { +import { HeaderCell } from './header-cell'; +export class CornerCell extends HeaderCell { protected headerConfig: CornerHeaderConfig; - protected textShapes: IShape[]; + protected textShapes: IShape[] = []; - protected handleRestOptions(...options) { - if (options.length === 0) { - throw new Error( - 'CornerCell render need headerConfig&hotConfig in CornerHeader!!!', - ); - } - this.headerConfig = options[0]; + public get cellType() { + return CellTypes.CORNER_CELL; } public update() {} @@ -38,20 +34,16 @@ export class CornerCell extends BaseCell { this.drawHotpot(); } - public get cellType() { - return CellTypes.CORNER_CELL; - } - protected drawCellText() { const { position } = this.headerConfig; const { label, x, y, width: cellWidth, height: cellHeight } = this.meta; - if (_.isEqual(label, EXTRA_FIELD)) { + if (isEqual(label, EXTRA_FIELD)) { // don't render extra node return; } - const cornerTheme = _.get(this.theme, 'cornerCell'); + const cornerTheme = get(this.theme, 'cornerCell'); const textStyle = { ...cornerTheme?.bolderText }; const iconStyle = cornerTheme?.icon; const cellPadding = cornerTheme?.cell?.padding; @@ -64,7 +56,7 @@ export class CornerCell extends BaseCell { } // 当为树状结构下需要计算文本前收起展开的icon占的位置 - const extraPadding = this.ifNeedIcon() + const extraPadding = this.shouldShowIcon() ? iconStyle?.size + iconStyle?.margin?.left + iconStyle?.margin?.right : 0; @@ -111,9 +103,7 @@ export class CornerCell extends BaseCell { }); const textY = - position.y + - y + - (_.isEmpty(secondLine) ? cellHeight / 2 : cellHeight / 4); + position.y + y + (isEmpty(secondLine) ? cellHeight / 2 : cellHeight / 4); // first line this.textShapes.push( renderText( @@ -128,7 +118,7 @@ export class CornerCell extends BaseCell { ); // second line - if (!_.isEmpty(secondLine)) { + if (!isEmpty(secondLine)) { this.textShapes.push( renderText( [this.textShapes[1]], @@ -143,7 +133,7 @@ export class CornerCell extends BaseCell { } // 如果为树状模式,角头第一个单元格前需要绘制收起展开的icon - if (this.ifNeedIcon()) { + if (this.shouldShowIcon()) { this.drawIcon(); } } @@ -155,8 +145,8 @@ export class CornerCell extends BaseCell { // 只有交叉表才有icon const { hierarchyCollapse, height, spreadsheet, position } = this.headerConfig; - const iconStyle = _.get(this.theme, 'cornerCell.icon'); - const textStyle = _.get(this.theme, 'cornerCell.text'); + const iconStyle = get(this.theme, 'cornerCell.icon'); + const textStyle = get(this.theme, 'cornerCell.text'); const colHeight = spreadsheet.options.style.colCfg.height; const icon = new GuiIcon({ type: hierarchyCollapse ? 'plus' : 'MinusSquare', @@ -182,7 +172,7 @@ export class CornerCell extends BaseCell { private drawCellRect() { const { position } = this.headerConfig; const { x, y, width: cellWidth, height: cellHeight } = this.meta; - const attrs: any = { + const attrs: ShapeAttrs = { x: position.x + x, y: position.y + y, width: cellWidth, @@ -194,9 +184,7 @@ export class CornerCell extends BaseCell { attrs.stroke = this.theme.cornerCell.cell.horizontalBorderColor; } - this.addShape('rect', { - attrs, - }); + this.backgroundShape = renderRect(this, attrs); } private drawHotpot() { @@ -232,7 +220,7 @@ export class CornerCell extends BaseCell { }); } - private ifNeedIcon() { + private shouldShowIcon() { // 批量折叠或者展开的icon,只存在树状结构的第一个cell前 return ( this.headerConfig.spreadsheet.isHierarchyTreeType() && diff --git a/packages/s2-core/src/cell/detail-col-cell.ts b/packages/s2-core/src/cell/detail-col-cell.ts index 7ba4a3ca06..5041a064e3 100644 --- a/packages/s2-core/src/cell/detail-col-cell.ts +++ b/packages/s2-core/src/cell/detail-col-cell.ts @@ -1,8 +1,9 @@ import { ColCell } from '@/cell/col-cell'; +import { renderText } from '@/utils/g-renders'; import { get } from 'lodash'; -import { getEllipsisText, getTextPosition } from '../utils/text'; import { EXTRA_FIELD } from '../common/constant'; import { addDetailTypeSortIcon } from '../facet/layout/util/add-detail-type-sort-icon'; +import { getEllipsisText, getTextPosition } from '../utils/text'; export class DetailColCell extends ColCell { protected drawCellText() { @@ -49,16 +50,18 @@ export class DetailColCell extends ColCell { textStyle, ); - this.addShape('text', { - attrs: { - x: textX, - y: textY, - text, + this.textShape = renderText( + [this.textShape], + textX, + textY, + text, + { textAlign, ...textStyle, - cursor: 'pointer', }, - }); + this, + { cursor: 'pointer' }, + ); addDetailTypeSortIcon( this, diff --git a/packages/s2-core/src/cell/header-cell.ts b/packages/s2-core/src/cell/header-cell.ts new file mode 100644 index 0000000000..a509cafbea --- /dev/null +++ b/packages/s2-core/src/cell/header-cell.ts @@ -0,0 +1,39 @@ +import { BaseHeaderConfig } from '@/facet/header/base'; +import { find } from 'lodash'; +import { BaseCell } from 'src/cell'; +import { Node, SpreadSheet } from '../index'; + +export abstract class HeaderCell extends BaseCell { + protected headerConfig: BaseHeaderConfig; + + constructor( + meta: Node, + spreadsheet: SpreadSheet, + headerConfig: BaseHeaderConfig, + ) { + super(meta, spreadsheet, headerConfig); + } + + protected handleRestOptions(...[headerConfig]: [BaseHeaderConfig]) { + this.headerConfig = headerConfig; + } + + public update() { + const selectedId = this.spreadsheet.store.get('rowColSelectedId'); + if (selectedId && find(selectedId, (id) => id === this.meta.id)) { + this.setActive(); + } else { + this.setInactive(); + } + } + + /** + * @description set active style, should be implemented by subtype + */ + public setActive() {} + + /** + * @description set inactive style, should be implemented by subtype + */ + public setInactive() {} +} diff --git a/packages/s2-core/src/cell/row-cell.ts b/packages/s2-core/src/cell/row-cell.ts index 9b8988b702..d0b108f75c 100644 --- a/packages/s2-core/src/cell/row-cell.ts +++ b/packages/s2-core/src/cell/row-cell.ts @@ -2,24 +2,24 @@ import { GuiIcon } from '@/common/icons'; import { HIT_AREA } from '@/facet/header/base'; import { ResizeInfo } from '@/facet/header/interface'; import { RowHeaderConfig } from '@/facet/header/row'; -import { renderRect, updateShapeAttr } from '@/utils/g-renders'; +import { renderRect, renderText, updateShapeAttr } from '@/utils/g-renders'; import { getAllChildrenNodeHeight } from '@/utils/get-all-children-node-height'; import { isMobile } from '@/utils/is-mobile'; import { getAdjustPosition } from '@/utils/text-absorption'; import { IGroup } from '@antv/g-canvas'; import { GM } from '@antv/g-gesture'; -import { each, find, get } from 'lodash'; +import { each, get } from 'lodash'; import { CellTypes, COLOR_DEFAULT_RESIZER, ID_SEPARATOR, KEY_COLLAPSE_TREE_ROWS, KEY_GROUP_ROW_RESIZER, + LINK_TEXT_COLOR_IN_HEADER, } from '../common/constant'; -import { Node } from '../index'; import { getEllipsisText, measureTextWidth } from '../utils/text'; -import { BaseCell } from './base-cell'; -export class RowCell extends BaseCell { +import { HeaderCell } from './header-cell'; +export class RowCell extends HeaderCell { protected headerConfig: RowHeaderConfig; // 绘制完其他后,需要额外绘制的起始x坐标 @@ -31,13 +31,8 @@ export class RowCell extends BaseCell { // mobile event private gm: GM; - public update() { - const selectedId = this.spreadsheet.store.get('rowColSelectedId'); - if (selectedId && find(selectedId, (id) => id === this.meta.id)) { - this.setActive(); - } else { - this.setInactive(); - } + public get cellType() { + return CellTypes.ROW_CELL; } public setActive() { @@ -55,11 +50,6 @@ export class RowCell extends BaseCell { this.gm?.destroy(); } - // TODO: options能不能不要固定顺序?headerConfig必须是 0下的吗? - protected handleRestOptions(...options: RowHeaderConfig[]) { - this.headerConfig = options[0]; - } - protected initCell() { // 1、draw rect background this.drawBackgroundColor(); @@ -76,16 +66,12 @@ export class RowCell extends BaseCell { this.drawActionIcons(); } - public get cellType() { - return CellTypes.ROW_CELL; - } - protected drawBackgroundColor() { const { rowCell: rowHeaderStyle } = this.spreadsheet.theme; const bgColor = rowHeaderStyle.cell.backgroundColor; const { x, y, height, width } = this.meta; - renderRect(this, { + this.backgroundShape = renderRect(this, { x, y, width, @@ -279,21 +265,22 @@ export class RowCell extends BaseCell { textTheme.fontSize, ); - const textShape = this.addShape('text', { - attrs: { - x: textX, - y: textY, - text, - ...textStyle, - cursor: 'pointer', - }, - }); + this.textShape = renderText( + [this.textShape], + textX, + textY, + text, + textStyle, + this, + { cursor: 'pointer' }, + ); + // handle link nodes if (linkFieldIds.includes(this.meta.key)) { const device = get(this.headerConfig, 'spreadsheet.options.style.device'); // 配置了链接跳转 if (!isMobile(device)) { - const textBBox = textShape.getBBox(); + const textBBox = this.textShape.getBBox(); this.addShape('line', { attrs: { x1: textBBox.bl.x, @@ -304,15 +291,15 @@ export class RowCell extends BaseCell { lineWidth: 1, }, }); - textShape.attr({ + this.textShape.attr({ appendInfo: { isRowHeaderText: true, // 标记为行头文本,方便做链接跳转直接识别 cellData: this.meta, }, }); } else { - textShape.attr({ - fill: '#0000ee', + this.textShape.attr({ + fill: LINK_TEXT_COLOR_IN_HEADER, appendInfo: { isRowHeaderText: true, // 标记为行头文本,方便做链接跳转直接识别 cellData: this.meta, diff --git a/packages/s2-core/src/common/constant/theme.ts b/packages/s2-core/src/common/constant/theme.ts index 74426243ed..582dc69e15 100644 --- a/packages/s2-core/src/common/constant/theme.ts +++ b/packages/s2-core/src/common/constant/theme.ts @@ -30,3 +30,5 @@ export const COLOR_DEFAULT_RESIZER = 'rgba(33,33,33,0)'; // default condition's icon export const UP_ICON = 'CellUp'; export const DOWN_ICON = 'CellDown'; + +export const LINK_TEXT_COLOR_IN_HEADER = '#0000ee'; diff --git a/packages/s2-core/src/utils/g-renders.ts b/packages/s2-core/src/utils/g-renders.ts index 22041b19db..592dfb9456 100644 --- a/packages/s2-core/src/utils/g-renders.ts +++ b/packages/s2-core/src/utils/g-renders.ts @@ -76,3 +76,11 @@ export function updateShapeAttr( set(shape, `attrs.${attribute}`, value); } } + +export function updateFillOpacity(shape: IShape, opacity: number) { + updateShapeAttr(shape, 'fillOpacity', opacity); +} + +export function updateStrokeOpacity(shape: IShape, opacity: number) { + updateShapeAttr(shape, 'strokeOpacity', opacity); +} From 658e9dee1fb189a686bd47d6b4a194a516a2c894 Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Tue, 17 Aug 2021 19:31:07 +0800 Subject: [PATCH 04/13] refactor: rename detail row cell to detail data cell --- .../src/cell/{detail-row-cell.ts => detail-data-cell.ts} | 2 +- packages/s2-core/src/cell/index.ts | 4 ++-- packages/s2-core/src/sheet-type/index.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename packages/s2-core/src/cell/{detail-row-cell.ts => detail-data-cell.ts} (97%) diff --git a/packages/s2-core/src/cell/detail-row-cell.ts b/packages/s2-core/src/cell/detail-data-cell.ts similarity index 97% rename from packages/s2-core/src/cell/detail-row-cell.ts rename to packages/s2-core/src/cell/detail-data-cell.ts index dec0f2409c..1095b93750 100644 --- a/packages/s2-core/src/cell/detail-row-cell.ts +++ b/packages/s2-core/src/cell/detail-data-cell.ts @@ -3,7 +3,7 @@ import { DataCell } from 'src/cell/data-cell'; import { renderText } from '../utils/g-renders'; import { isMobile } from '../utils/is-mobile'; import { getEllipsisText, getTextPosition } from '../utils/text'; -export class DetailRowCell extends DataCell { +export class DetailDataCell extends DataCell { protected drawTextShape() { const { x, y, height, width } = this.getContentAreaBBox(); const { formattedValue: text } = this.getData(); diff --git a/packages/s2-core/src/cell/index.ts b/packages/s2-core/src/cell/index.ts index dd150b5842..a64aba29ca 100644 --- a/packages/s2-core/src/cell/index.ts +++ b/packages/s2-core/src/cell/index.ts @@ -4,12 +4,12 @@ import { CornerCell } from './corner-cell'; import { DataCell } from './data-cell'; import { MergedCells } from './merged-cells'; import { RowCell } from './row-cell'; -import { DetailRowCell } from './detail-row-cell'; +import { DetailDataCell } from './detail-data-cell'; import { DetailColCell } from './detail-col-cell'; export { DetailColCell, - DetailRowCell, + DetailDataCell, RowCell, ColCell, DataCell, diff --git a/packages/s2-core/src/sheet-type/index.ts b/packages/s2-core/src/sheet-type/index.ts index 5ed2da7fc6..1c6fafab98 100644 --- a/packages/s2-core/src/sheet-type/index.ts +++ b/packages/s2-core/src/sheet-type/index.ts @@ -1,4 +1,4 @@ -import { BaseCell, DataCell, DetailRowCell } from '@/cell'; +import { BaseCell, DataCell, DetailDataCell } from '@/cell'; import { KEY_AFTER_COLLAPSE_ROWS, KEY_COLLAPSE_ROWS, @@ -465,7 +465,7 @@ export class SpreadSheet extends EE { this.options.showSeriesNumber && facet.colIndex === 0 ) { - return new DetailRowCell(facet, this); + return new DetailDataCell(facet, this); } return new DataCell(facet, this); }; From 1d52b361adcf280bdeb9f9b2e78d645ae53678b4 Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Wed, 18 Aug 2021 14:09:02 +0800 Subject: [PATCH 05/13] refactor: refine function declaration in data cell --- packages/s2-core/src/cell/base-cell.ts | 3 ++ packages/s2-core/src/cell/data-cell.ts | 39 +++++++------------ .../s2-core/src/common/interface/basic.ts | 5 ++- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/packages/s2-core/src/cell/base-cell.ts b/packages/s2-core/src/cell/base-cell.ts index 364f8dc8c9..ddecef22b4 100644 --- a/packages/s2-core/src/cell/base-cell.ts +++ b/packages/s2-core/src/cell/base-cell.ts @@ -32,6 +32,9 @@ export abstract class BaseCell extends Group { // render interactive background, protected interactiveBgShape: IShape; + // brush-select prepareSelect border + protected activeBorderShape: IShape; + // 需要根据state改变样式的shape集合 // 需要这个属性的原因是在state clear时知道具体哪些shape要hide。不然只能手动改,比较麻烦 protected stateShapes: IShape[] = []; diff --git a/packages/s2-core/src/cell/data-cell.ts b/packages/s2-core/src/cell/data-cell.ts index 0cc0e8182b..c6fc1cdf22 100644 --- a/packages/s2-core/src/cell/data-cell.ts +++ b/packages/s2-core/src/cell/data-cell.ts @@ -23,7 +23,7 @@ import { renderLine, renderRect, renderText } from '@/utils/g-renders'; import { getEllipsisText } from '@/utils/text'; import { IShape, SimpleBBox } from '@antv/g-canvas'; import { find, first, get, includes, isEmpty, map } from 'lodash'; -import type { SpreadSheet } from 'src/sheet-type'; +import { ViewMetaIndex } from './../common/interface/basic'; /** * DataCell for panelGroup area @@ -38,7 +38,10 @@ import type { SpreadSheet } from 'src/sheet-type'; * 3、left rect area is interval(in left) and text(in right) */ export class DataCell extends BaseCell { - // 3、condition shapes + // cell configs conditions(Determine how to render this cell) + protected conditions: Conditions; + + // condition shapes // background color by bg condition protected conditionBgShape: IShape; @@ -48,30 +51,18 @@ export class DataCell extends BaseCell { // interval condition shape protected intervalShape: IShape; - // 4、render main text - protected textShape: IShape; - - // 5、brush-select prepareSelect border - protected activeBorderShape: IShape; - - // cell configs conditions(Determine how to render this cell) - protected conditions: Conditions; - - constructor(meta: ViewMeta, spreadsheet: SpreadSheet) { - super(meta, spreadsheet); + public get cellType() { + return CellTypes.DATA_CELL; } protected handleSelect(cells: S2CellType[]) { // 如果当前选择点击选择了行头或者列头,那么与行头列头在一个colIndex或rowIndex的data-cell应该置为selected-state // 二者操作一致,function合并 const currentCellType = cells?.[0]?.cellType; - if (currentCellType === CellTypes.COL_CELL) { - this.changeCellStyleByState('colIndex', InteractionStateName.SELECTED); - return; - } - if (currentCellType === CellTypes.ROW_CELL) { - this.changeCellStyleByState('rowIndex', InteractionStateName.SELECTED); - } + this.changeCellStyleByState( + currentCellType === CellTypes.COL_CELL ? 'colIndex' : 'rowIndex', + InteractionStateName.SELECTED, + ); } protected handleHover(cells: S2CellType[]) { @@ -214,7 +205,7 @@ export class DataCell extends BaseCell { this.initCell(); } - public setCellsSpotlight() { + protected setCellsSpotlight() { if ( this.spreadsheet.options.selectedCellsSpotlight && this.spreadsheet.interaction.isSelectedState() && @@ -236,10 +227,6 @@ export class DataCell extends BaseCell { this.setCellsSpotlight(); } - public get cellType() { - return CellTypes.DATA_CELL; - } - // 根据state要改变样式的shape protected drawStateShapes() { this.drawInteractiveBgShape(); @@ -509,7 +496,7 @@ export class DataCell extends BaseCell { // dataCell根据state 改变当前样式, private changeCellStyleByState( - index: 'colIndex' | 'rowIndex', + index: ViewMetaIndex, stateName: InteractionStateName, ) { const cells = this.spreadsheet.interaction.getActiveCells(); diff --git a/packages/s2-core/src/common/interface/basic.ts b/packages/s2-core/src/common/interface/basic.ts index 5ec908128e..920a61af6a 100644 --- a/packages/s2-core/src/common/interface/basic.ts +++ b/packages/s2-core/src/common/interface/basic.ts @@ -12,8 +12,8 @@ import { BaseDataSet } from 'src/data-set'; import { Frame } from 'src/facet/header'; import { Padding } from '../interface/theme'; import { BaseTooltip } from '../tooltip'; -import { DataItem, S2DataConfig } from './s2DataConfig'; import { S2CellType } from './interaction'; +import { DataItem, S2DataConfig } from './s2DataConfig'; import { IconTheme } from './theme'; export type Formatter = (v: unknown) => string; @@ -375,6 +375,9 @@ export interface ViewMeta { colId?: string; [key: string]: any; } + +export type ViewMetaIndex = keyof Pick; + export type GetCellMeta = (rowIndex: number, colIndex: number) => ViewMeta; export interface LayoutResult { From 002c80be1e349ba3310bad7c6187970e263d496b Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Wed, 18 Aug 2021 14:27:12 +0800 Subject: [PATCH 06/13] refactor: refine merge cell constructor --- packages/s2-core/src/cell/merged-cells.ts | 27 +++++++++++++++-------- packages/s2-core/src/utils/text.ts | 4 ++-- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/packages/s2-core/src/cell/merged-cells.ts b/packages/s2-core/src/cell/merged-cells.ts index 3fc333a2bd..c26e8fc835 100644 --- a/packages/s2-core/src/cell/merged-cells.ts +++ b/packages/s2-core/src/cell/merged-cells.ts @@ -1,3 +1,4 @@ +import { SpreadSheet } from '@/sheet-type'; import { getPolygonPoints } from '@/utils/interaction/merge-cells'; import { IShape, SimpleBBox } from '@antv/g-canvas'; import { isEmpty, isObject } from 'lodash'; @@ -17,6 +18,22 @@ export class MergedCells extends BaseCell { protected textShape: IShape; + public constructor( + meta: ViewMeta, + spreadsheet: SpreadSheet, + cells: S2CellType[], + ) { + super(meta, spreadsheet, cells); + } + + handleRestOptions(...[cells]: [S2CellType[]]) { + this.cells = cells; + } + + public get cellType() { + return CellTypes.MERGED_CELLS; + } + public update() {} public getData(): { value: DataItem; formattedValue: DataItem } { @@ -39,10 +56,6 @@ export class MergedCells extends BaseCell { }; } - handleRestOptions(...options: S2CellType[][]) { - this.cells = options[0]; - } - protected initCell() { // TODO:1、条件格式支持; 2、交互态扩展; 3、合并后的单元格文字布局及文字内容(目前参考Excel合并后只保留第一个单元格子的数据) this.drawBackgroundShape(); @@ -51,15 +64,11 @@ export class MergedCells extends BaseCell { // this.update(); } - public get cellType() { - return CellTypes.MERGED_CELLS; - } - /** * Get left rest area size by icon condition * @protected */ - protected getLeftAreaBBox(): SimpleBBox { + protected getContentAreaBBox(): SimpleBBox { const { x, y, height, width } = this.meta; return { x, diff --git a/packages/s2-core/src/utils/text.ts b/packages/s2-core/src/utils/text.ts index ce0868e84c..22f982a7b8 100644 --- a/packages/s2-core/src/utils/text.ts +++ b/packages/s2-core/src/utils/text.ts @@ -297,7 +297,7 @@ const getStyle = ( * @param cell */ export const drawObjectText = (cell) => { - const { x, y, height, width } = cell.getLeftAreaBBox(); + const { x, y, height, width } = cell.getContentAreaBBox(); const { formattedValue: text } = cell.getData(); const labelStyle = cell.theme?.view?.bolderText; const textStyle = cell.theme?.view?.text; @@ -362,7 +362,7 @@ export const drawObjectText = (cell) => { * @returns 文本左上角起点坐标 */ export const drawStringText = (cell) => { - const { x, y, height, width } = cell.getLeftAreaBBox(); + const { x, y, height, width } = cell.getContentAreaBBox(); const { formattedValue: text } = cell.getData(); const { isTotals } = cell.meta; const textStyle = isTotals From 2245b4b86ef6bdff5007744e9b29c249a5535dbe Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Wed, 18 Aug 2021 15:26:53 +0800 Subject: [PATCH 07/13] refactor: unify stateShapes --- packages/s2-core/src/cell/base-cell.ts | 35 ++++++++------- packages/s2-core/src/cell/col-cell.ts | 32 +++++++++----- packages/s2-core/src/cell/data-cell.ts | 44 +++++++++---------- packages/s2-core/src/cell/row-cell.ts | 26 ++++++----- .../src/common/constant/interaction.ts | 4 +- .../src/common/interface/interaction.ts | 2 + .../src/utils/interaction/merge-cells.ts | 22 +++++----- 7 files changed, 90 insertions(+), 75 deletions(-) diff --git a/packages/s2-core/src/cell/base-cell.ts b/packages/s2-core/src/cell/base-cell.ts index ddecef22b4..293de0197f 100644 --- a/packages/s2-core/src/cell/base-cell.ts +++ b/packages/s2-core/src/cell/base-cell.ts @@ -13,6 +13,7 @@ import { updateShapeAttr, updateStrokeOpacity, } from '../utils/g-renders'; +import { StateShapeLayer } from './../common/interface/interaction'; export abstract class BaseCell extends Group { // cell's data meta info @@ -24,22 +25,14 @@ export abstract class BaseCell extends Group { // spreadsheet's theme protected theme: SpreadSheetTheme; - // background control by icon condition + // background control shape protected backgroundShape: IShape; + // text control shape protected textShape: IShape; - // render interactive background, - protected interactiveBgShape: IShape; - - // brush-select prepareSelect border - protected activeBorderShape: IShape; - - // 需要根据state改变样式的shape集合 - // 需要这个属性的原因是在state clear时知道具体哪些shape要hide。不然只能手动改,比较麻烦 - protected stateShapes: IShape[] = []; - - // protected actionIcons: GuiIcon[]; + // interactive control shapes, unify read and manipulate operations + protected stateShapes = new Map(); public constructor( meta: T, @@ -95,16 +88,24 @@ export abstract class BaseCell extends Group { each(stateStyles, (style, styleKey) => { const currentShape = findKey(SHAPE_ATTRS_MAP, (attrs) => includes(attrs, styleKey), + ) as StateShapeLayer | undefined; + + if (!currentShape || !this.stateShapes.has(currentShape)) { + return; + } + + updateShapeAttr( + this.stateShapes.get(currentShape), + SHAPE_STYLE_MAP[styleKey], + style, ); - if (!currentShape) return; - updateShapeAttr(this[currentShape], SHAPE_STYLE_MAP[styleKey], style); this.showShapeUnderState(currentShape); }); } - private showShapeUnderState(currentShape: string) { - updateFillOpacity(this[currentShape], 1); - updateStrokeOpacity(this[currentShape], 1); + private showShapeUnderState(currentShape: StateShapeLayer) { + updateFillOpacity(this.stateShapes.get(currentShape), 1); + updateStrokeOpacity(this.stateShapes.get(currentShape), 1); } public hideShapeUnderState() { diff --git a/packages/s2-core/src/cell/col-cell.ts b/packages/s2-core/src/cell/col-cell.ts index af1cdab3de..f63e52f0b6 100644 --- a/packages/s2-core/src/cell/col-cell.ts +++ b/packages/s2-core/src/cell/col-cell.ts @@ -8,7 +8,12 @@ import { TextAlign } from '@/common/interface/theme'; import { HIT_AREA } from '@/facet/header/base'; import { ColHeaderConfig } from '@/facet/header/col'; import { ResizeInfo } from '@/facet/header/interface'; -import { renderRect, renderText, updateShapeAttr } from '@/utils/g-renders'; +import { + renderRect, + renderText, + updateFillOpacity, + updateShapeAttr, +} from '@/utils/g-renders'; import { getEllipsisText, getTextPosition, @@ -27,14 +32,14 @@ export class ColCell extends HeaderCell { public setActive() { updateShapeAttr( - this.interactiveBgShape, + this.stateShapes.get('interactiveBgShape'), 'fill', this.theme.colCell.cell.selectedBackgroundColor, ); } public setInactive() { - updateShapeAttr(this.interactiveBgShape, 'fillOpacity', 0); + updateFillOpacity(this.stateShapes.get('interactiveBgShape'), 0); } protected initCell() { @@ -50,6 +55,7 @@ export class ColCell extends HeaderCell { this.drawRightBorder(); // 5、draw hot-spot rect this.drawHotSpot(); + this.update(); } protected getColHotSpotKey() { @@ -203,15 +209,17 @@ export class ColCell extends HeaderCell { // 交互使用的背景色 protected drawInteractiveBgShape() { const { x, y, height, width } = this.meta; - this.interactiveBgShape = renderRect(this, { - x, - y, - width, - height, - fill: 'transparent', - stroke: 'transparent', - }); - this.stateShapes.push(this.interactiveBgShape); + this.stateShapes.set( + 'interactiveBgShape', + renderRect(this, { + x, + y, + width, + height, + fill: 'transparent', + stroke: 'transparent', + }), + ); } private showSortIcon() { diff --git a/packages/s2-core/src/cell/data-cell.ts b/packages/s2-core/src/cell/data-cell.ts index c6fc1cdf22..d4a96aa09c 100644 --- a/packages/s2-core/src/cell/data-cell.ts +++ b/packages/s2-core/src/cell/data-cell.ts @@ -126,10 +126,6 @@ export class DataCell extends BaseCell { }; } - public getInteractiveBgShape() { - return this.interactiveBgShape; - } - /** * @description get cell text style * @protected @@ -380,15 +376,17 @@ export class DataCell extends BaseCell { // 往内缩一个像素,避免和外边框重叠 const margin = 1; const { x, y, height, width } = this.meta; - this.activeBorderShape = renderRect(this, { - x: x + margin, - y: y + margin, - width: width - margin * 2, - height: height - margin * 2, - fill: 'transparent', - stroke: 'transparent', - }); - this.stateShapes.push(this.activeBorderShape); + this.stateShapes.set( + 'activeBorderShape', + renderRect(this, { + x: x + margin, + y: y + margin, + width: width - margin * 2, + height: height - margin * 2, + fill: 'transparent', + stroke: 'transparent', + }), + ); } /** @@ -396,15 +394,17 @@ export class DataCell extends BaseCell { */ protected drawInteractiveBgShape() { const { x, y, height, width } = this.meta; - this.interactiveBgShape = renderRect(this, { - x, - y, - width, - height, - fill: 'transparent', - stroke: 'transparent', - }); - this.stateShapes.push(this.interactiveBgShape); + this.stateShapes.set( + 'interactiveBgShape', + renderRect(this, { + x, + y, + width, + height, + fill: 'transparent', + stroke: 'transparent', + }), + ); } /** diff --git a/packages/s2-core/src/cell/row-cell.ts b/packages/s2-core/src/cell/row-cell.ts index d0b108f75c..ab09c19518 100644 --- a/packages/s2-core/src/cell/row-cell.ts +++ b/packages/s2-core/src/cell/row-cell.ts @@ -2,7 +2,7 @@ import { GuiIcon } from '@/common/icons'; import { HIT_AREA } from '@/facet/header/base'; import { ResizeInfo } from '@/facet/header/interface'; import { RowHeaderConfig } from '@/facet/header/row'; -import { renderRect, renderText, updateShapeAttr } from '@/utils/g-renders'; +import { renderRect, renderText, updateFillOpacity } from '@/utils/g-renders'; import { getAllChildrenNodeHeight } from '@/utils/get-all-children-node-height'; import { isMobile } from '@/utils/is-mobile'; import { getAdjustPosition } from '@/utils/text-absorption'; @@ -36,12 +36,12 @@ export class RowCell extends HeaderCell { } public setActive() { - updateShapeAttr(this.interactiveBgShape, 'fillOpacity', 1); + updateFillOpacity(this.stateShapes.get('interactiveBgShape'), 1); each(this.actionIcons, (icon) => icon.set('visible', true)); } public setInactive() { - updateShapeAttr(this.interactiveBgShape, 'fillOpacity', 0); + updateFillOpacity(this.stateShapes.get('interactiveBgShape'), 0); // each(this.actionIcons, (icon) => icon.set('visible', false)); } @@ -85,15 +85,17 @@ export class RowCell extends HeaderCell { // 交互使用的背景色 protected drawInteractiveBgShape() { const { x, y, height, width } = this.meta; - this.interactiveBgShape = renderRect(this, { - x, - y, - width, - height, - fill: 'transparent', - stroke: 'transparent', - }); - this.stateShapes.push(this.interactiveBgShape); + this.stateShapes.set( + 'interactiveBgShape', + renderRect(this, { + x, + y, + width, + height, + fill: 'transparent', + stroke: 'transparent', + }), + ); } protected drawIconInTree() { diff --git a/packages/s2-core/src/common/constant/interaction.ts b/packages/s2-core/src/common/constant/interaction.ts index 5cc52d72af..34a2d1dcc1 100644 --- a/packages/s2-core/src/common/constant/interaction.ts +++ b/packages/s2-core/src/common/constant/interaction.ts @@ -1,3 +1,4 @@ +import { StateShapeLayer } from './../interface/interaction'; export enum InteractionNames { BRUSH_SELECTION_INTERACTION = 'spreadsheet:brush-selection', COL_ROW_RESIZE_INTERACTION = 'spreadsheet:row-col-resize', @@ -10,6 +11,7 @@ export enum InteractionStateName { HOVER = 'hover', HOVER_FOCUS = 'hoverFocus', PREPARE_SELECT = 'prepareSelect', + OUT_OF_SPOTLIGHT = 'outOfTheSpotlight', } export enum CellTypes { @@ -32,7 +34,7 @@ export const SHAPE_STYLE_MAP = { }; // 设置属性的时候实际对应改变的shape映射 -export const SHAPE_ATTRS_MAP = { +export const SHAPE_ATTRS_MAP: { [K in StateShapeLayer]: string[] } = { interactiveBgShape: ['backgroundColor', 'opacity'], activeBorderShape: ['borderColor', 'backgroundColor'], }; diff --git a/packages/s2-core/src/common/interface/interaction.ts b/packages/s2-core/src/common/interface/interaction.ts index 918771d95d..b4c1ab0d81 100644 --- a/packages/s2-core/src/common/interface/interaction.ts +++ b/packages/s2-core/src/common/interface/interaction.ts @@ -33,3 +33,5 @@ export interface S2CellBrushRange { width: number; height: number; } + +export type StateShapeLayer = 'interactiveBgShape' | 'activeBorderShape'; diff --git a/packages/s2-core/src/utils/interaction/merge-cells.ts b/packages/s2-core/src/utils/interaction/merge-cells.ts index 1df421db02..2e5babd788 100644 --- a/packages/s2-core/src/utils/interaction/merge-cells.ts +++ b/packages/s2-core/src/utils/interaction/merge-cells.ts @@ -1,15 +1,15 @@ import { + filter, find, - isEqual, forEach, + isArray, isEmpty, - filter, + isEqual, merge, - isArray, } from 'lodash'; -import { S2CellType } from 'src/common/interface/interaction'; -import { MergedCellInfo } from 'src/common/interface/index'; import { MergedCells } from 'src/cell/merged-cells'; +import { MergedCellInfo } from 'src/common/interface/index'; +import { S2CellType } from 'src/common/interface/interaction'; import { SpreadSheet } from 'src/sheet-type'; /** @@ -146,10 +146,10 @@ export const mergeCells = ( cellsInfo: MergedCellInfo[], hideData?: boolean, ) => { - const allCells = (filter( + const allCells = filter( sheet.panelGroup.getChildren(), (child) => !(child instanceof MergedCells), - ) as unknown) as S2CellType[]; + ) as unknown as S2CellType[]; const { cells, viewMeta } = getCellsByInfo(cellsInfo, allCells); if (!isEmpty(cells)) { @@ -192,10 +192,10 @@ export const updateMergedCells = (sheet: SpreadSheet) => { const mergedCellsInfo = sheet.options?.mergedCellsInfo; if (isEmpty(mergedCellsInfo)) return; - const allCells = (filter( + const allCells = filter( sheet.panelGroup.getChildren(), (child) => !(child instanceof MergedCells), - ) as unknown) as S2CellType[]; + ) as unknown as S2CellType[]; if (isEmpty(allCells)) return; const allMergedCells = []; @@ -203,10 +203,10 @@ export const updateMergedCells = (sheet: SpreadSheet) => { allMergedCells.push(getCellsByInfo(cellsInfo, allCells)); }); - const oldMergedCells = (filter( + const oldMergedCells = filter( sheet.panelGroup.getChildren(), (child) => child instanceof MergedCells, - ) as unknown) as MergedCells; + ) as unknown as MergedCells; allMergedCells.forEach((mergedCell) => { const { cells, viewMeta } = mergedCell; From e15f85a684e99f55a4ffd5cca1f9414e11f3e088 Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Wed, 18 Aug 2021 16:42:54 +0800 Subject: [PATCH 08/13] refactor: refactor render util function --- packages/s2-core/src/cell/col-cell.ts | 15 +++++--- packages/s2-core/src/cell/corner-cell.ts | 4 +- packages/s2-core/src/cell/data-cell.ts | 38 +++++++++++-------- packages/s2-core/src/cell/detail-col-cell.ts | 2 +- packages/s2-core/src/cell/detail-data-cell.ts | 13 +++++-- packages/s2-core/src/cell/merged-cells.ts | 4 +- packages/s2-core/src/cell/row-cell.ts | 30 +++++++++------ packages/s2-core/src/utils/g-renders.ts | 23 ++++------- packages/s2-core/src/utils/text.ts | 6 +-- 9 files changed, 75 insertions(+), 60 deletions(-) diff --git a/packages/s2-core/src/cell/col-cell.ts b/packages/s2-core/src/cell/col-cell.ts index f63e52f0b6..46bcdbd221 100644 --- a/packages/s2-core/src/cell/col-cell.ts +++ b/packages/s2-core/src/cell/col-cell.ts @@ -9,6 +9,7 @@ import { HIT_AREA } from '@/facet/header/base'; import { ColHeaderConfig } from '@/facet/header/col'; import { ResizeInfo } from '@/facet/header/interface'; import { + renderLine, renderRect, renderText, updateFillOpacity, @@ -193,6 +194,7 @@ export class ColCell extends HeaderCell { // } // } this.textShape = renderText( + this, [this.textShape], textX, textY, @@ -201,7 +203,6 @@ export class ColCell extends HeaderCell { textAlign, ...textStyle, }, - this, { cursor: 'pointer' }, ); } @@ -327,16 +328,20 @@ export class ColCell extends HeaderCell { if (!this.meta.isLeaf) { const { height, viewportHeight } = this.headerConfig; const { x, y, width: cellWidth, height: cellHeight } = this.meta; - this.addShape('line', { - attrs: { + + renderLine( + this, + { x1: x + cellWidth, y1: y + cellHeight, x2: x + cellWidth, - y2: y + height + viewportHeight, // 高度有多,通过 clip 裁剪掉 + y2: y + height + viewportHeight, + }, + { stroke: this.theme.colCell.cell.horizontalBorderColor, lineWidth: 1, }, - }); + ); } } } diff --git a/packages/s2-core/src/cell/corner-cell.ts b/packages/s2-core/src/cell/corner-cell.ts index 0b444862d1..e04214e27a 100644 --- a/packages/s2-core/src/cell/corner-cell.ts +++ b/packages/s2-core/src/cell/corner-cell.ts @@ -107,12 +107,12 @@ export class CornerCell extends HeaderCell { // first line this.textShapes.push( renderText( + this, [this.textShapes[0]], textX, textY, firstLine, textStyle, - this, extraInfo, ), ); @@ -121,12 +121,12 @@ export class CornerCell extends HeaderCell { if (!isEmpty(secondLine)) { this.textShapes.push( renderText( + this, [this.textShapes[1]], textX, position.y + y + cellHeight * 0.65, secondLine, textStyle, - this, extraInfo, ), ); diff --git a/packages/s2-core/src/cell/data-cell.ts b/packages/s2-core/src/cell/data-cell.ts index d4a96aa09c..7c6a4e0e49 100644 --- a/packages/s2-core/src/cell/data-cell.ts +++ b/packages/s2-core/src/cell/data-cell.ts @@ -291,12 +291,12 @@ export class DataCell extends BaseCell { const position = this.getTextPosition(); this.textShape = renderText( + this, [this.textShape], position.x, position.y, ellipsisText, { ...textStyle, fill: textFill }, - this, ); } @@ -523,26 +523,34 @@ export class DataCell extends BaseCell { // horizontal border renderLine( - x, - y, - x + width, - y, - cell.horizontalBorderColor, - cell.horizontalBorderWidth, this, - cell.horizontalBorderColorOpacity, + { + x1: x, + y1: y, + x2: x + width, + y2: y, + }, + { + stroke: cell.horizontalBorderColor, + lineWidth: cell.horizontalBorderWidth, + opacity: cell.horizontalBorderColorOpacity, + }, ); // vertical border renderLine( - x + width, - y, - x + width, - y + height, - cell.verticalBorderColor, - cell.verticalBorderWidth, this, - cell.horizontalBorderColorOpacity, + { + x1: x + width, + y1: y, + x2: x + width, + y2: y + height, + }, + { + stroke: cell.verticalBorderColor, + lineWidth: cell.verticalBorderWidth, + opacity: cell.horizontalBorderColorOpacity, + }, ); } } diff --git a/packages/s2-core/src/cell/detail-col-cell.ts b/packages/s2-core/src/cell/detail-col-cell.ts index 5041a064e3..e45b5dae0f 100644 --- a/packages/s2-core/src/cell/detail-col-cell.ts +++ b/packages/s2-core/src/cell/detail-col-cell.ts @@ -51,6 +51,7 @@ export class DetailColCell extends ColCell { ); this.textShape = renderText( + this, [this.textShape], textX, textY, @@ -59,7 +60,6 @@ export class DetailColCell extends ColCell { textAlign, ...textStyle, }, - this, { cursor: 'pointer' }, ); diff --git a/packages/s2-core/src/cell/detail-data-cell.ts b/packages/s2-core/src/cell/detail-data-cell.ts index 1095b93750..b8765d04ee 100644 --- a/packages/s2-core/src/cell/detail-data-cell.ts +++ b/packages/s2-core/src/cell/detail-data-cell.ts @@ -1,3 +1,4 @@ +import { renderLine } from '@/utils/g-renders'; import { get } from 'lodash'; import { DataCell } from 'src/cell/data-cell'; import { renderText } from '../utils/g-renders'; @@ -26,12 +27,12 @@ export class DetailDataCell extends DataCell { }; const position = getTextPosition(cellBoxCfg); this.textShape = renderText( + this, [this.textShape], position.x, position.y, ellipsisText, textStyle, - this, ); const linkFieldIds = get(this.spreadsheet, 'options.linkFieldIds'); @@ -42,16 +43,20 @@ export class DetailDataCell extends DataCell { // 配置了链接跳转 if (!isMobile(device)) { const textBBox = this.textShape.getBBox(); - this.addShape('line', { - attrs: { + renderLine( + this, + { x1: textBBox.bl.x, y1: textBBox.bl.y + 1, x2: textBBox.br.x, y2: textBBox.br.y + 1, + }, + { stroke: textStyle.fill, lineWidth: 1, }, - }); + ); + this.textShape.attr({ appendInfo: { isRowHeaderText: true, // 标记为行头文本,方便做链接跳转直接识别 diff --git a/packages/s2-core/src/cell/merged-cells.ts b/packages/s2-core/src/cell/merged-cells.ts index c26e8fc835..e234b141a8 100644 --- a/packages/s2-core/src/cell/merged-cells.ts +++ b/packages/s2-core/src/cell/merged-cells.ts @@ -1,6 +1,6 @@ import { SpreadSheet } from '@/sheet-type'; import { getPolygonPoints } from '@/utils/interaction/merge-cells'; -import { IShape, SimpleBBox } from '@antv/g-canvas'; +import { SimpleBBox } from '@antv/g-canvas'; import { isEmpty, isObject } from 'lodash'; import { S2CellType } from 'src/common/interface/interaction'; import { renderPolygon } from 'src/utils/g-renders'; @@ -16,8 +16,6 @@ import { BaseCell } from './base-cell'; export class MergedCells extends BaseCell { public cells: S2CellType[]; - protected textShape: IShape; - public constructor( meta: ViewMeta, spreadsheet: SpreadSheet, diff --git a/packages/s2-core/src/cell/row-cell.ts b/packages/s2-core/src/cell/row-cell.ts index ab09c19518..5f1da4aed9 100644 --- a/packages/s2-core/src/cell/row-cell.ts +++ b/packages/s2-core/src/cell/row-cell.ts @@ -2,7 +2,12 @@ import { GuiIcon } from '@/common/icons'; import { HIT_AREA } from '@/facet/header/base'; import { ResizeInfo } from '@/facet/header/interface'; import { RowHeaderConfig } from '@/facet/header/row'; -import { renderRect, renderText, updateFillOpacity } from '@/utils/g-renders'; +import { + renderLine, + renderRect, + renderText, + updateFillOpacity, +} from '@/utils/g-renders'; import { getAllChildrenNodeHeight } from '@/utils/get-all-children-node-height'; import { isMobile } from '@/utils/is-mobile'; import { getAdjustPosition } from '@/utils/text-absorption'; @@ -176,17 +181,20 @@ export class RowCell extends HeaderCell { const { x, y } = this.meta; // 1、bottom border const textIndent = this.getTextIndent(); - this.addShape('line', { - attrs: { + renderLine( + this, + { x1: x + textIndent, y1: y, x2: position.x + width + viewportWidth + scrollX, y2: y, + }, + { stroke: this.theme.rowCell.cell.horizontalBorderColor, - opacity: this.theme.rowCell.cell.horizontalBorderOpacity, lineWidth: this.theme.rowCell.cell.horizontalBorderWidth, + opacity: this.theme.rowCell.cell.horizontalBorderOpacity, }, - }); + ); } protected isTreeType() { @@ -268,12 +276,12 @@ export class RowCell extends HeaderCell { ); this.textShape = renderText( + this, [this.textShape], textX, textY, text, textStyle, - this, { cursor: 'pointer' }, ); @@ -283,16 +291,16 @@ export class RowCell extends HeaderCell { // 配置了链接跳转 if (!isMobile(device)) { const textBBox = this.textShape.getBBox(); - this.addShape('line', { - attrs: { + renderLine( + this, + { x1: textBBox.bl.x, y1: textBBox.bl.y + 1, x2: textBBox.br.x, y2: textBBox.br.y + 1, - stroke: textStyle.fill, - lineWidth: 1, }, - }); + { stroke: textStyle.fill, lineWidth: 1 }, + ); this.textShape.attr({ appendInfo: { isRowHeaderText: true, // 标记为行头文本,方便做链接跳转直接识别 diff --git a/packages/s2-core/src/utils/g-renders.ts b/packages/s2-core/src/utils/g-renders.ts index 592dfb9456..01d788cb1b 100644 --- a/packages/s2-core/src/utils/g-renders.ts +++ b/packages/s2-core/src/utils/g-renders.ts @@ -20,13 +20,13 @@ export function renderPolygon(group: Group, attrs: ShapeAttrs): IShape { } export function renderText( + group: Group, shapes: IShape[], x: number, y: number, text: string, textStyle: TextTheme, - group: Group, - extraStyle?: any, + extraStyle?: ShapeAttrs, ): IShape { if (!isEmpty(shapes) && group) { forEach(shapes, (shape: IShape) => { @@ -45,24 +45,15 @@ export function renderText( } export function renderLine( - x1: number, - y1: number, - x2: number, - y2: number, - stroke: string, - lineWidth: number, group: Group, - opacity?: number, + coordinate: { x1: number; y1: number; x2: number; y2: number }, + lineStyle: Pick, ): IShape { return group?.addShape?.('line', { + zIndex: 100, attrs: { - x1, - y1, - x2, - y2, - stroke, - opacity, - lineWidth, + ...coordinate, + ...lineStyle, }, }); } diff --git a/packages/s2-core/src/utils/text.ts b/packages/s2-core/src/utils/text.ts index 22f982a7b8..bceb76f791 100644 --- a/packages/s2-core/src/utils/text.ts +++ b/packages/s2-core/src/utils/text.ts @@ -308,6 +308,7 @@ export const drawObjectText = (cell) => { const realWidth = width / (text?.values[0].length + 1); const realHeight = height / (text?.values.length + 1); renderText( + cell, cell.textShape, calX(x, padding), y + realHeight / 2, @@ -318,7 +319,6 @@ export const drawObjectText = (cell) => { ), labelStyle, textFill, - cell, ); const { values: textValues } = text; @@ -344,13 +344,13 @@ export const drawObjectText = (cell) => { curX = calX(x, padding, totalWidth); totalWidth += curWidth; curTextShape = renderText( + cell, cell.textShape, curX, curY, getEllipsisText(`${curText}`, curWidth, curStyle), curStyle, curStyle?.fill, - cell, ); } } @@ -372,6 +372,7 @@ export const drawStringText = (cell) => { const padding = cell.theme.dataCell.cell.padding; cell.textShape = renderText( + cell, cell.textShape, x + width - padding.right, y + height / 2, @@ -382,7 +383,6 @@ export const drawStringText = (cell) => { ), textStyle, textFill, - cell, ); }; From 62bf36892b55d07fb7190ec9afef9eac4f002efa Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Wed, 18 Aug 2021 17:44:37 +0800 Subject: [PATCH 09/13] refactor: unify interaction state --- packages/s2-core/src/cell/base-cell.ts | 5 +- packages/s2-core/src/cell/col-cell.ts | 2 +- .../s2-core/src/common/interface/theme.ts | 17 ++- packages/s2-core/src/facet/header/corner.ts | 14 +-- packages/s2-core/src/theme/index.ts | 112 ++++++++++-------- 5 files changed, 81 insertions(+), 69 deletions(-) diff --git a/packages/s2-core/src/cell/base-cell.ts b/packages/s2-core/src/cell/base-cell.ts index 293de0197f..dcd9948106 100644 --- a/packages/s2-core/src/cell/base-cell.ts +++ b/packages/s2-core/src/cell/base-cell.ts @@ -84,7 +84,10 @@ export abstract class BaseCell extends Group { // 根据当前state来更新cell的样式 public updateByState(stateName: InteractionStateName) { - const stateStyles = get(this.theme, `${this.cellType}.cell.${stateName}`); + const stateStyles = get( + this.theme, + `${this.cellType}.cell.interactionState.${stateName}`, + ); each(stateStyles, (style, styleKey) => { const currentShape = findKey(SHAPE_ATTRS_MAP, (attrs) => includes(attrs, styleKey), diff --git a/packages/s2-core/src/cell/col-cell.ts b/packages/s2-core/src/cell/col-cell.ts index 46bcdbd221..7284ffa9a1 100644 --- a/packages/s2-core/src/cell/col-cell.ts +++ b/packages/s2-core/src/cell/col-cell.ts @@ -35,7 +35,7 @@ export class ColCell extends HeaderCell { updateShapeAttr( this.stateShapes.get('interactiveBgShape'), 'fill', - this.theme.colCell.cell.selectedBackgroundColor, + this.theme.colCell.cell.interactionState.selected.backgroundColor, ); } diff --git a/packages/s2-core/src/common/interface/theme.ts b/packages/s2-core/src/common/interface/theme.ts index 2919cf5f1e..61450a96e8 100644 --- a/packages/s2-core/src/common/interface/theme.ts +++ b/packages/s2-core/src/common/interface/theme.ts @@ -1,3 +1,5 @@ +import { InteractionStateName } from '../constant'; + // 文本内容的水平对齐方式, 默认 left export type TextAlign = 'left' | 'center' | 'right'; @@ -30,6 +32,10 @@ export interface InteractionStateTheme { opacity?: string | number; } +export type InteractionState = { + [K in InteractionStateName]?: InteractionStateTheme; +}; + export type Margin = Padding; export interface TextTheme { @@ -63,18 +69,9 @@ export interface CellTheme { verticalBorderWidth?: number; /* 单元格内边距 */ padding: Padding; - /* hover 单元格状态 */ - hover?: InteractionStateTheme; - /* hover 焦点单元格 */ - hoverFocus?: InteractionStateTheme; - /* 选中态 */ - selected?: InteractionStateTheme; - /* 预选中态 */ - prepareSelect?: InteractionStateTheme; + interactionState?: InteractionState; /* 单元格内条件格式-迷你条形图高度 */ miniBarChartHeight?: number; - /* 聚光灯之外的单元格 */ - outOfTheSpotlight?: InteractionStateTheme; /* 额外属性字段 */ [key: string]: any; } diff --git a/packages/s2-core/src/facet/header/corner.ts b/packages/s2-core/src/facet/header/corner.ts index a24f5a538e..1bd8e2f3ba 100644 --- a/packages/s2-core/src/facet/header/corner.ts +++ b/packages/s2-core/src/facet/header/corner.ts @@ -1,21 +1,21 @@ -import { SimpleBBox, Group, Point } from '@antv/g-canvas'; -import { get, last, includes, isEmpty } from 'lodash'; import { i18n } from '@/common/i18n'; +import { BaseDataSet } from '@/data-set'; +import { Group, Point, SimpleBBox } from '@antv/g-canvas'; +import { get, includes, isEmpty, last } from 'lodash'; import { - KEY_SERIES_NUMBER_NODE, - KEY_GROUP_CORNER_RESIZER, COLOR_DEFAULT_RESIZER, + KEY_GROUP_CORNER_RESIZER, + KEY_SERIES_NUMBER_NODE, } from '../../common/constant'; -import { BaseDataSet } from '@/data-set'; -import { SpreadSheet, Hierarchy, Node, CornerCell } from '../../index'; import { LayoutResult, S2Options, SpreadSheetFacetCfg, } from '../../common/interface'; +import { CornerCell, Hierarchy, Node, SpreadSheet } from '../../index'; +import { translateGroup } from '../utils'; import { BaseHeader, BaseHeaderConfig, HIT_AREA } from './base'; import { CornerData, ResizeInfo } from './interface'; -import { translateGroup } from '../utils'; export interface CornerHeaderConfig extends BaseHeaderConfig { // header's hierarchy type diff --git a/packages/s2-core/src/theme/index.ts b/packages/s2-core/src/theme/index.ts index 026508eb20..4174760d19 100644 --- a/packages/s2-core/src/theme/index.ts +++ b/packages/s2-core/src/theme/index.ts @@ -50,15 +50,18 @@ export const getTheme = (themeCfg: ThemeCfg): SpreadSheetTheme => { bottom: 12, left: 8, }, - // -------------- hover ------------------- - hover: { - backgroundColor: brandColors[5], - }, - // -------------- selected ------------------- - selected: { - backgroundColor: brandColors[5], - borderColor: grayColors[6], - borderWidth: 1, + /* ---------- interaction state ----------- */ + interactionState: { + // -------------- hover ------------------- + hover: { + backgroundColor: brandColors[5], + }, + // -------------- selected ------------------- + selected: { + backgroundColor: brandColors[5], + borderColor: grayColors[6], + borderWidth: 1, + }, }, }, icon: { @@ -108,15 +111,18 @@ export const getTheme = (themeCfg: ThemeCfg): SpreadSheetTheme => { bottom: 12, left: 8, }, - // -------------- hover ------------------- - hover: { - backgroundColor: brandColors[2], - }, - // -------------- selected ------------------- - selected: { - backgroundColor: brandColors[2], - borderColor: grayColors[6], - borderWidth: 1, + /* ---------- interaction state ----------- */ + interactionState: { + // -------------- hover ------------------- + hover: { + backgroundColor: brandColors[2], + }, + // -------------- selected ------------------- + selected: { + backgroundColor: brandColors[2], + borderColor: grayColors[6], + borderWidth: 1, + }, }, }, icon: { @@ -166,15 +172,18 @@ export const getTheme = (themeCfg: ThemeCfg): SpreadSheetTheme => { bottom: 12, left: 8, }, - // -------------- hover ------------------- - hover: { - backgroundColor: brandColors[5], - }, - // -------------- selected ------------------- - selected: { - backgroundColor: brandColors[5], - borderColor: grayColors[6], - borderWidth: 1, + /* ---------- interaction state ----------- */ + interactionState: { + // -------------- hover ------------------- + hover: { + backgroundColor: brandColors[5], + }, + // -------------- selected ------------------- + selected: { + backgroundColor: brandColors[5], + borderColor: grayColors[6], + borderWidth: 1, + }, }, }, icon: { @@ -227,29 +236,32 @@ export const getTheme = (themeCfg: ThemeCfg): SpreadSheetTheme => { bottom: 12, left: 8, }, - // -------------- hover ------------------- - hover: { - backgroundColor: brandColors[2], - }, - // -------------- keep hover ------------------- - hoverFocus: { - backgroundColor: brandColors[2], - borderColor: grayColors[6], - borderWidth: 1, - }, - // -------------- selected ------------------- - selected: { - backgroundColor: brandColors[2], - borderColor: grayColors[6], - borderWidth: 1, - }, - // -------------- prepare select -------------- - prepareSelect: { - borderColor: brandColors[3], - }, - // -------------- out of spotlight -------------- - outOfTheSpotlight: { - opacity: 0.3, + /* ---------- interaction state ----------- */ + interactionState: { + // -------------- hover ------------------- + hover: { + backgroundColor: brandColors[2], + }, + // -------------- keep hover ------------------- + hoverFocus: { + backgroundColor: brandColors[2], + borderColor: grayColors[6], + borderWidth: 1, + }, + // -------------- selected ------------------- + selected: { + backgroundColor: brandColors[2], + borderColor: grayColors[6], + borderWidth: 1, + }, + // -------------- prepare select -------------- + prepareSelect: { + borderColor: brandColors[3], + }, + // -------------- out of spotlight -------------- + outOfTheSpotlight: { + opacity: 0.3, + }, }, // ------------- mini chart --------------- miniBarChartHeight: MINI_BAR_CHART_HEIGHT, From d06f0380a81bf865b9940ba7a58c731a21ef4253 Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Fri, 20 Aug 2021 12:46:02 +0800 Subject: [PATCH 10/13] refactor: extract link text variable to theme config --- packages/s2-core/src/cell/col-cell.ts | 4 ++-- packages/s2-core/src/cell/row-cell.ts | 3 +-- packages/s2-core/src/common/constant/theme.ts | 2 -- packages/s2-core/src/common/interface/theme.ts | 3 +++ packages/s2-core/src/theme/index.ts | 5 ++++- packages/s2-core/src/theme/palette/colorful-blue.ts | 1 + packages/s2-core/src/theme/palette/default.ts | 1 + packages/s2-core/src/theme/palette/simple-blue.ts | 1 + 8 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/s2-core/src/cell/col-cell.ts b/packages/s2-core/src/cell/col-cell.ts index 7284ffa9a1..aa18adbffc 100644 --- a/packages/s2-core/src/cell/col-cell.ts +++ b/packages/s2-core/src/cell/col-cell.ts @@ -116,8 +116,8 @@ export class ColCell extends HeaderCell { let textAlign: TextAlign; if (isLeaf) { // 最后一个层级的维值,与 dataCell 对齐方式保持一致 - textAlign = get(this, 'theme.dataCell.text.textAlign'); - const textBaseline = get(this, 'theme.dataCell.text.textBaseline'); + textAlign = this.theme.dataCell.text.textAlign; + const textBaseline = this.theme.dataCell.text.textBaseline; textStyle.textBaseline = textBaseline; const cellBoxCfg = { x, diff --git a/packages/s2-core/src/cell/row-cell.ts b/packages/s2-core/src/cell/row-cell.ts index 5f1da4aed9..da004c678d 100644 --- a/packages/s2-core/src/cell/row-cell.ts +++ b/packages/s2-core/src/cell/row-cell.ts @@ -20,7 +20,6 @@ import { ID_SEPARATOR, KEY_COLLAPSE_TREE_ROWS, KEY_GROUP_ROW_RESIZER, - LINK_TEXT_COLOR_IN_HEADER, } from '../common/constant'; import { getEllipsisText, measureTextWidth } from '../utils/text'; import { HeaderCell } from './header-cell'; @@ -309,7 +308,7 @@ export class RowCell extends HeaderCell { }); } else { this.textShape.attr({ - fill: LINK_TEXT_COLOR_IN_HEADER, + fill: textTheme.linkTextFill, appendInfo: { isRowHeaderText: true, // 标记为行头文本,方便做链接跳转直接识别 cellData: this.meta, diff --git a/packages/s2-core/src/common/constant/theme.ts b/packages/s2-core/src/common/constant/theme.ts index 582dc69e15..74426243ed 100644 --- a/packages/s2-core/src/common/constant/theme.ts +++ b/packages/s2-core/src/common/constant/theme.ts @@ -30,5 +30,3 @@ export const COLOR_DEFAULT_RESIZER = 'rgba(33,33,33,0)'; // default condition's icon export const UP_ICON = 'CellUp'; export const DOWN_ICON = 'CellDown'; - -export const LINK_TEXT_COLOR_IN_HEADER = '#0000ee'; diff --git a/packages/s2-core/src/common/interface/theme.ts b/packages/s2-core/src/common/interface/theme.ts index 61450a96e8..19db58d74f 100644 --- a/packages/s2-core/src/common/interface/theme.ts +++ b/packages/s2-core/src/common/interface/theme.ts @@ -5,6 +5,7 @@ export type TextAlign = 'left' | 'center' | 'right'; // 绘制文本时的基线, 对应垂直方向对齐方式 默认 bottom export type TextBaseline = 'top' | 'middle' | 'bottom'; + export interface Palette { /* brand colors */ brandColors: string[]; @@ -14,6 +15,7 @@ export interface Palette { semanticColors: { red?: string; green?: string; + blue?: string; /* 额外颜色字段 */ [key: string]: string; }; @@ -43,6 +45,7 @@ export interface TextTheme { fontSize?: number; fontWeight?: string; fill?: string; + linkTextFill?: string; opacity?: number; textAlign?: TextAlign; textBaseline?: TextBaseline; diff --git a/packages/s2-core/src/theme/index.ts b/packages/s2-core/src/theme/index.ts index 4174760d19..f59806a831 100644 --- a/packages/s2-core/src/theme/index.ts +++ b/packages/s2-core/src/theme/index.ts @@ -7,7 +7,9 @@ import { getPalette } from '../utils/theme'; * @describe generate the theme according to the type * @param name */ -export const getTheme = (themeCfg: ThemeCfg): SpreadSheetTheme => { +export const getTheme = ( + themeCfg: Omit, +): SpreadSheetTheme => { const themePalette: Palette = themeCfg?.palette || getPalette(themeCfg?.name, themeCfg?.hueInvert); const { brandColors, grayColors, semanticColors } = themePalette; @@ -89,6 +91,7 @@ export const getTheme = (themeCfg: ThemeCfg): SpreadSheetTheme => { fontSize: 12, fontWeight: 'normal', fill: grayColors[6], + linkTextFill: semanticColors.blue, opacity: 1, textAlign: 'right', }, diff --git a/packages/s2-core/src/theme/palette/colorful-blue.ts b/packages/s2-core/src/theme/palette/colorful-blue.ts index 4935631a4a..a55c8ec441 100644 --- a/packages/s2-core/src/theme/palette/colorful-blue.ts +++ b/packages/s2-core/src/theme/palette/colorful-blue.ts @@ -24,5 +24,6 @@ export const paletteColorfulBlue = { semanticColors: { red: '#FF4D4F', green: '#29A294', + blue: '#0000ee', }, }; diff --git a/packages/s2-core/src/theme/palette/default.ts b/packages/s2-core/src/theme/palette/default.ts index b0c217a985..835ead4073 100644 --- a/packages/s2-core/src/theme/palette/default.ts +++ b/packages/s2-core/src/theme/palette/default.ts @@ -24,5 +24,6 @@ export const paletteDefault = { semanticColors: { red: '#FF4D4F', green: '#29A294', + blue: '#0000ee', }, }; diff --git a/packages/s2-core/src/theme/palette/simple-blue.ts b/packages/s2-core/src/theme/palette/simple-blue.ts index 73340a60c4..e93d5cadb7 100644 --- a/packages/s2-core/src/theme/palette/simple-blue.ts +++ b/packages/s2-core/src/theme/palette/simple-blue.ts @@ -24,5 +24,6 @@ export const paletteSimpleBlue = { semanticColors: { red: '#FF4D4F', green: '#29A294', + blue: '#0000ee', }, }; From 8ab5dd6609287b46930b77a1c4b6ccaffe6b1e21 Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Fri, 20 Aug 2021 14:48:45 +0800 Subject: [PATCH 11/13] refactor: rename interactive shape --- packages/s2-core/src/cell/data-cell.ts | 2 +- packages/s2-core/src/common/interface/interaction.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/s2-core/src/cell/data-cell.ts b/packages/s2-core/src/cell/data-cell.ts index 183a0a9195..f13bffbd66 100644 --- a/packages/s2-core/src/cell/data-cell.ts +++ b/packages/s2-core/src/cell/data-cell.ts @@ -399,7 +399,7 @@ export class DataCell extends BaseCell { const margin = 1; const { x, y, height, width } = this.meta; this.stateShapes.set( - 'activeBorderShape', + 'interactiveBorderShape', renderRect(this, { x: x + margin, y: y + margin, diff --git a/packages/s2-core/src/common/interface/interaction.ts b/packages/s2-core/src/common/interface/interaction.ts index db1f5f9dac..57066e1b57 100644 --- a/packages/s2-core/src/common/interface/interaction.ts +++ b/packages/s2-core/src/common/interface/interaction.ts @@ -41,4 +41,4 @@ export interface S2CellBrushRange { height?: number; } -export type StateShapeLayer = 'interactiveBgShape' | 'activeBorderShape'; +export type StateShapeLayer = 'interactiveBgShape' | 'interactiveBorderShape'; From cb14be7b855eea09fa51ff5b87aacfd2d65d2eab Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Fri, 20 Aug 2021 15:22:37 +0800 Subject: [PATCH 12/13] chore: close loop for test:live --- packages/s2-core/scripts/test-live.js | 1 + packages/s2-core/src/cell/row-cell.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/s2-core/scripts/test-live.js b/packages/s2-core/scripts/test-live.js index 91b413b941..a00045f15d 100644 --- a/packages/s2-core/scripts/test-live.js +++ b/packages/s2-core/scripts/test-live.js @@ -19,6 +19,7 @@ async function main() { type: 'list', message: '请选择测试文件', name: 'path', + loop: false, choices: paths, default: () => defaultFilename, }, diff --git a/packages/s2-core/src/cell/row-cell.ts b/packages/s2-core/src/cell/row-cell.ts index 617dd404c5..e8159f7edb 100644 --- a/packages/s2-core/src/cell/row-cell.ts +++ b/packages/s2-core/src/cell/row-cell.ts @@ -18,6 +18,8 @@ import { GM } from '@antv/g-gesture'; import { get } from 'lodash'; import { getEllipsisText, measureTextWidth } from '../utils/text'; import { HeaderCell } from './header-cell'; + +console.log(HeaderCell); export class RowCell extends HeaderCell { protected headerConfig: RowHeaderConfig; From 9783132a482f765e1356b9d04400d8ee688bbdae Mon Sep 17 00:00:00 2001 From: wjgogogo <906626481@qq.com> Date: Fri, 20 Aug 2021 17:48:32 +0800 Subject: [PATCH 13/13] fix: remove blue color, add link field color into brand colors --- packages/s2-core/src/theme/index.ts | 2 +- packages/s2-core/src/theme/palette/colorful-blue.ts | 2 +- packages/s2-core/src/theme/palette/default.ts | 2 +- packages/s2-core/src/theme/palette/simple-blue.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/s2-core/src/theme/index.ts b/packages/s2-core/src/theme/index.ts index 6ed89b7506..b30d0145d6 100644 --- a/packages/s2-core/src/theme/index.ts +++ b/packages/s2-core/src/theme/index.ts @@ -78,7 +78,7 @@ export const getTheme = ( fontSize: 12, fontWeight: 'normal', fill: grayColors[6], - linkTextFill: semanticColors.blue, + linkTextFill: brandColors[7], opacity: 1, textAlign: 'right', }, diff --git a/packages/s2-core/src/theme/palette/colorful-blue.ts b/packages/s2-core/src/theme/palette/colorful-blue.ts index 5d0a707318..c9fd2de770 100644 --- a/packages/s2-core/src/theme/palette/colorful-blue.ts +++ b/packages/s2-core/src/theme/palette/colorful-blue.ts @@ -8,6 +8,7 @@ export const paletteColorfulBlue = { '#3471F9', '#2C60D3', '#2C60D3', + '#0000ee', ], // ----------neutral colors ---------- @@ -25,6 +26,5 @@ export const paletteColorfulBlue = { semanticColors: { red: '#FF4D4F', green: '#29A294', - blue: '#0000ee', }, }; diff --git a/packages/s2-core/src/theme/palette/default.ts b/packages/s2-core/src/theme/palette/default.ts index 9b5b54ad70..6df5249f42 100644 --- a/packages/s2-core/src/theme/palette/default.ts +++ b/packages/s2-core/src/theme/palette/default.ts @@ -8,6 +8,7 @@ export const paletteDefault = { '#ffffff', '#D9EAFF', '#2C60D3', + '#0000ee', ], // ----------neutral colors ---------- @@ -25,6 +26,5 @@ export const paletteDefault = { semanticColors: { red: '#FF4D4F', green: '#29A294', - blue: '#0000ee', }, }; diff --git a/packages/s2-core/src/theme/palette/simple-blue.ts b/packages/s2-core/src/theme/palette/simple-blue.ts index 9508c9981b..f06ffe7abd 100644 --- a/packages/s2-core/src/theme/palette/simple-blue.ts +++ b/packages/s2-core/src/theme/palette/simple-blue.ts @@ -8,6 +8,7 @@ export const paletteSimpleBlue = { '#E0E9FE', '#CCDBFD', '#2C60D3', + '#0000ee', ], // ----------neutral colors ---------- @@ -25,6 +26,5 @@ export const paletteSimpleBlue = { semanticColors: { red: '#FF4D4F', green: '#29A294', - blue: '#0000ee', }, };