Skip to content

Commit

Permalink
feat: 趋势分析表支持子弹图配置 (#1367)
Browse files Browse the repository at this point in the history
* feat: 趋势分析表增支持添加子弹图

* fix: fix ci

* style: 增加标记线透明度

* refactor: 变量名变更
  • Loading branch information
xingwanying authored May 31, 2022
1 parent c63ebd0 commit b5756cc
Show file tree
Hide file tree
Showing 14 changed files with 270 additions and 30 deletions.
20 changes: 7 additions & 13 deletions packages/s2-core/src/cell/base-cell.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
import { BBox, Group, IShape, Point, SimpleBBox } from '@antv/g-canvas';
import {
each,
get,
includes,
isBoolean,
isFunction,
isNumber,
keys,
pickBy,
} from 'lodash';
import { each, get, includes, isBoolean, isNumber, keys, pickBy } from 'lodash';
import {
CellTypes,
InteractionStateName,
Expand All @@ -17,6 +8,7 @@ import {
} from '@/common/constant';
import {
CellThemes,
DefaultCellTheme,
FormatResult,
ResizeActiveOptions,
ResizeArea,
Expand Down Expand Up @@ -153,12 +145,12 @@ export abstract class BaseCell<T extends SimpleBBox> extends Group {

public getStyle<K extends keyof S2Theme = keyof CellThemes>(
name?: K,
): S2Theme[K] {
): DefaultCellTheme | S2Theme[K] {
return this.theme[name || this.cellType];
}

protected getResizeAreaStyle(): ResizeArea {
return this.getStyle('resizeArea');
return this.getStyle('resizeArea') as ResizeArea;
}

protected shouldDrawResizeAreaByType(type: keyof ResizeActiveOptions) {
Expand All @@ -177,7 +169,9 @@ export abstract class BaseCell<T extends SimpleBBox> extends Group {

// get content area that exclude padding
public getContentArea() {
const { padding } = this.getStyle()?.cell || this.theme.dataCell.cell;
const cellStyle = (this.getStyle() ||
this.theme.dataCell) as DefaultCellTheme;
const { padding } = cellStyle?.cell;
return getContentArea(this.getCellArea(), padding);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/s2-core/src/common/interface/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ export interface CellCfg {
// 原始值字段
originalValueField?: string;
// 每一列数值占单元格宽度百分比 Map
widthPercentCfg?: number[];
widthPercent?: number[];
// 条件格式
conditions?: { text: Condition };
};
Expand Down
14 changes: 11 additions & 3 deletions packages/s2-core/src/common/interface/s2DataConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ import {
SortParams,
} from '@/common/interface/index';

/* 子弹图数据结构 */
export interface BulletValue {
// 当前指标
measure: number | string;
// 目标值
target: number | string;
[key: string]: unknown;
}

/** use for gridAnalysisSheet
* eg. { label: '余额女',
values: [
Expand All @@ -15,10 +24,9 @@ import {
],
}
*/

export interface MultiData {
values: (string | number)[][];
originalValues?: (string | number)[][];
values: (string | number)[][] | BulletValue;
originalValues?: (string | number)[][] | BulletValue;
// the title of one cell of the gridAnalysisSheet
label?: string;
[key: string]: unknown;
Expand Down
38 changes: 38 additions & 0 deletions packages/s2-core/src/common/interface/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface PaletteMeta {
semanticColors: {
red?: string;
green?: string;
yellow?: string;
[key: string]: string;
};
/* 补充色值 */
Expand Down Expand Up @@ -246,6 +247,8 @@ export interface S2Theme extends CellThemes {
scrollBar?: ScrollBarTheme;
/* 分割线样式 */
splitLine?: SplitLine;
/* 趋势分析表子弹图样式配置 */
bullet?: BulletTheme;
/* 刷选遮罩 */
prepareSelectMask?: InteractionStateTheme;
/* 画布背景底色 */
Expand All @@ -262,3 +265,38 @@ export interface ThemeCfg {
/* 主题名 */
name?: ThemeName;
}

/* 趋势分析表子弹图状态颜色 */
export interface RangeColors {
/* 满意 */
good: string;
/* 良好 */
satisfactory: string;
/* 不符合预期 */
bad: string;
}

/* 趋势分析表子弹图样式配置 */
export interface BulletTheme {
/* 进度条 */
progressBar: {
/* 子弹图宽度相对整体单元格的占比,小数, default:0.7 */
widthPercent: number;
height: number;
/* 内高度 */
innerHeight: number;
};

/* 测量标记线 */
comparativeMeasure: {
width: number;
height: number;
color?: string;
opacity?: number;
};

/* 子弹图状态颜色 */
rangeColors: RangeColors;
/* 子弹图背景色 */
backgroundColor: string;
}
20 changes: 20 additions & 0 deletions packages/s2-core/src/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,26 @@ export const getTheme = (
right: 'rgba(0,0,0,0)',
},
},
// ------------- bullet graph -----------------
bullet: {
progressBar: {
widthPercent: 0.7,
height: 10,
innerHeight: 6,
},
comparativeMeasure: {
width: 1,
height: 12,
color: basicColors[13],
opacity: 0.25,
},
rangeColors: {
good: semanticColors?.green,
satisfactory: semanticColors.yellow,
bad: semanticColors.red,
},
backgroundColor: '#E9E9E9',
},
// ------------- prepareSelectMask -----------------
prepareSelectMask: {
backgroundColor: basicColors[5],
Expand Down
1 change: 1 addition & 0 deletions packages/s2-core/src/theme/palette/colorful.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const paletteColorfulMeta: PaletteMeta = {
semanticColors: {
red: '#FF4D4F',
green: '#29A294',
yellow: '#FAAD14',
},
others: {
// ---------- searchResults colors ----------
Expand Down
1 change: 1 addition & 0 deletions packages/s2-core/src/theme/palette/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const paletteDefaultMeta: PaletteMeta = {
semanticColors: {
red: '#FF4D4F',
green: '#29A294',
yellow: '#FAAD14',
},
others: {
// ---------- searchResults colors ----------
Expand Down
1 change: 1 addition & 0 deletions packages/s2-core/src/theme/palette/gray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const paletteGrayMeta: PaletteMeta = {
semanticColors: {
red: '#FF4D4F',
green: '#29A294',
yellow: '#FAAD14',
},
others: {
// ---------- searchResults colors ----------
Expand Down
2 changes: 1 addition & 1 deletion packages/s2-core/src/utils/export/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const download = (str: string, fileName: string) => {
*/
const processObjectValueInCol = (data: MultiData) => {
const tempCells = data?.label ? [data?.label] : [];
const values = data?.values;
const values = data?.values as (string | number)[][];
if (!isEmpty(values)) {
forEach(values, (value) => {
tempCells.push(value.join(' '));
Expand Down
127 changes: 120 additions & 7 deletions packages/s2-core/src/utils/text.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
clone,
get,
isArray,
isEmpty,
isFunction,
Expand All @@ -12,10 +13,15 @@ import {
trim,
values,
} from 'lodash';
import { DefaultCellTheme, TextAlign } from '@/common/interface/theme';
import { renderText } from '@/utils/g-renders';
import {
BulletTheme,
DefaultCellTheme,
RangeColors,
} from '@/common/interface/theme';
import { renderLine, renderText, renderRect } from '@/utils/g-renders';
import { CellTypes, EMPTY_PLACEHOLDER } from '@/common/constant';
import {
BulletValue,
CellCfg,
Condition,
MultiData,
Expand Down Expand Up @@ -327,6 +333,108 @@ export const getEmptyPlaceholder = (
return isFunction(placeHolder) ? placeHolder(meta) : placeHolder;
};

/**
* 根据当前值和目标值获取子弹图填充色
*/
export const getBulletRangeColor = (
measure: number | string,
target: number | string,
rangeColors: RangeColors,
) => {
const delta = Number(target) - Number(measure);

if (delta <= 0.1) {
return rangeColors.good;
}

if (delta > 0.1 && delta <= 0.2) {
return rangeColors.satisfactory;
}
return rangeColors.bad;
};

/**
* 绘制子弹图单元格
*/
export const drawBullet = (value: BulletValue, cell: S2CellType) => {
if (isEmpty(value)) {
return;
}
const dataCellStyle = cell.getStyle(CellTypes.DATA_CELL);
const bulletStyle = cell.getStyle('bullet') as BulletTheme;
const { x, y, height, width } = cell.getMeta();
const { progressBar, comparativeMeasure, rangeColors, backgroundColor } =
bulletStyle;
const bulletWidth = progressBar.widthPercent * width;
const measureWidth = width - bulletWidth;

const padding = dataCellStyle.cell.padding;
const { measure, target } = value;

// TODO 先支持默认右对齐
// 绘制子弹图
// 1. 背景
const positionX = x + width - padding.right - bulletWidth;
const positionY = y + height / 2 - progressBar.height / 2;
renderRect(cell, {
x: positionX,
y: positionY,
width: bulletWidth,
height: progressBar.height,
fill: backgroundColor,
textBaseline: dataCellStyle.text.textBaseline,
});

// 2. 进度条
const getRangeColor = get(
cell.getMeta(),
'spreadsheet.options.bullet.getRangeColor',
);
renderRect(cell, {
x: positionX,
y: positionY + (progressBar.height - progressBar.innerHeight) / 2,
width: Math.min(bulletWidth * Number(measure), bulletWidth),
height: progressBar.innerHeight,
fill:
getRangeColor?.(measure, target) ??
getBulletRangeColor(measure, target, rangeColors),
});

// 3.测量标记线
const lineX = positionX + bulletWidth * Number(target);
renderLine(
cell,
{
x1: lineX,
y1: y + (height - comparativeMeasure.height) / 2,
x2: lineX,
y2:
y +
(height - comparativeMeasure.height) / 2 +
comparativeMeasure.height,
},
{
stroke: comparativeMeasure.color,
lineWidth: comparativeMeasure.width,
opacity: comparativeMeasure?.opacity,
},
);

// 绘制指标
renderText(
cell,
[],
positionX - padding.right,
y + height / 2,
getEllipsisText({
text: `${Number(measure) * 100}%`,
maxWidth: measureWidth,
fontParam: dataCellStyle.text,
}),
dataCellStyle.text,
);
};

/**
* @desc draw text shape of object
* @param cell
Expand All @@ -336,6 +444,7 @@ export const getEmptyPlaceholder = (
export const drawObjectText = (
cell: S2CellType,
multiData?: MultiData,
// 绘制指标列头需要禁用
disabledConditions?: boolean,
) => {
const { x } = cell.getTextAndIconPosition(0).text;
Expand All @@ -345,15 +454,20 @@ export const drawObjectText = (
width: totalTextWidth,
} = cell.getContentArea();
const text = multiData || (cell.getMeta().fieldValue as MultiData);
const { values: textValues } = text;
const { valuesCfg } = cell?.getMeta().spreadsheet.options.style.cellCfg;
const textCondition = disabledConditions ? null : valuesCfg?.conditions?.text;
if (!isArray(textValues)) {
drawBullet(textValues, cell);
return;
}

const widthPercentCfg = valuesCfg?.widthPercentCfg;
const widthPercent = valuesCfg?.widthPercent;
const dataCellStyle = cell.getStyle(CellTypes.DATA_CELL);
const { textAlign } = dataCellStyle.text;
const padding = dataCellStyle.cell.padding;

const realHeight = totalTextHeight / (text.values.length + 1);
const realHeight = totalTextHeight / (textValues.length + 1);
let labelHeight = 0;
// 绘制单元格主标题
if (text?.label) {
Expand All @@ -375,7 +489,6 @@ export const drawObjectText = (
}

// 绘制指标
const { values: textValues } = text;
let curText: string | number;
let curX: number;
let curY: number = y + realHeight / 2;
Expand All @@ -399,8 +512,8 @@ export const drawObjectText = (
dataCellStyle,
textCondition,
);
curWidth = !isEmpty(widthPercentCfg)
? totalTextWidth * (widthPercentCfg[j] / 100)
curWidth = !isEmpty(widthPercent)
? totalTextWidth * (widthPercent[j] / 100)
: totalTextWidth / text.values[0].length; // 指标个数相同,任取其一即可

curX = calX(x, padding.right, totalWidth, textAlign);
Expand Down
Loading

0 comments on commit b5756cc

Please sign in to comment.