Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(consionBar): 转化分析图 + 水波图 #3131

Merged
merged 1 commit into from Mar 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
61 changes: 49 additions & 12 deletions examples/case/statistical-scenario/demo/conversion-funnel.ts
@@ -1,4 +1,4 @@
import { Column, G2 } from '@antv/g2plot';
import { Column, G2, addWaterWave } from '@antv/g2plot';

const X_FIELD = 'stage';
const Y_FIELD = 'count';
Expand Down Expand Up @@ -64,28 +64,31 @@ G2.registerShape('interval', 'link-funnel', {
rectPath = this.parsePath(rectPath);

const group = container.addGroup();

// 灰色背景
group.addShape('path', {
capture: false,
attrs: {
...attrs,
fill: '#efefef',
fill: '#fff',
lineWidth: 1,
path: this.parsePath([
['M', points[0].x, points[1].y],
['M', points[0].x, 0],
['L', points[0].x, 1],
['L', points[2].x, 1],
['L', points[2].x, points[1].y],
['L', points[2].x, 0],
]),
},
});
// 实际柱子
group.addShape('path', {
name: 'column',
attrs: {
...attrs,
path: rectPath,
},
});

const boxPath = this.parsePath([
['M', points[0].x, 0],
['L', points[0].x, 1],
['L', points[2].x, 1],
['L', points[2].x, 0],
['L', points[0].x, 0],
]);

// 存在下一节点, 添加连接带
if (nextPoints) {
const linkPath = this.parsePath([
Expand Down Expand Up @@ -118,6 +121,40 @@ G2.registerShape('interval', 'link-funnel', {
},
});
}

/** 水波 ---- */
const centerX = (rectPath[0][1] + rectPath[2][1]) / 2;
const centerY = (boxPath[0][2] + boxPath[1][2]) / 2;
const height = boxPath[0][2] - boxPath[1][2];
const r = 1 - (rectPath[0][2] - rectPath[1][2]) / height;
// 1. 绘制一个波
const waves = group.addGroup({
name: 'waves',
});

const waveLength = 30;
// 3. 波对应的 clip 裁剪形状
const clipPath = waves.setClip({
type: 'path',
attrs: {
path: boxPath,
},
});

// 4. 绘制波形
addWaterWave(
centerX,
centerY,
r,
2,
{ fill: attrs.fill, opacity: 0.8 },
waves,
clipPath,
height,
waveLength,
undefined
);

return group;
},
});
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Expand Up @@ -115,7 +115,7 @@ export { Funnel, FUNNEL_CONVERSATION_FIELD } from './plots/funnel';
export type { FunnelOptions } from './plots/funnel';

// 水波图及类型定义 | author by [CarisL](https://github.com/CarisL), [hustcc](https://github.com/hustcc), [pearmini](https://github.com/pearmini)
export { Liquid } from './plots/liquid';
export { Liquid, addWaterWave } from './plots/liquid';
export type { LiquidOptions } from './plots/liquid';

// 子弹图及类型定义 | author by [arcsin1](https://github.com/arcsin1)
Expand Down
2 changes: 2 additions & 0 deletions src/plots/liquid/index.ts
Expand Up @@ -8,6 +8,8 @@ import { getLiquidData } from './utils';
// register liquid shape
import './shapes/liquid';

export { addWaterWave } from './shapes/liquid';

export type { LiquidOptions };

/**
Expand Down
24 changes: 16 additions & 8 deletions src/plots/liquid/shapes/liquid.ts
Expand Up @@ -203,7 +203,7 @@ function getWaterWavePath(
* @param radius 绘制图形的高度
* @param waveLength 波的长度
*/
function addWaterWave(
export function addWaterWave(
x: number,
y: number,
level: number,
Expand All @@ -215,16 +215,21 @@ function addWaterWave(
waveLength: number,
animation: LiquidOptions['animation']
) {
// 盒子属性 颜色 宽高
const { fill, opacity } = waveAttrs;
const bbox = clip.getBBox();
const width = bbox.maxX - bbox.minX;
const height = bbox.maxY - bbox.minY;

// 循环 waveCount 个数
for (let idx = 0; idx < waveCount; idx++) {
const factor = waveCount <= 1 ? 0 : idx / (waveCount - 1);

// 画波
const wave = group.addShape('path', {
name: `waterwave-path`,
attrs: {
// 波形路径配置
path: getWaterWavePath(
radius,
bbox.minY + height * level,
Expand All @@ -240,6 +245,7 @@ function addWaterWave(
});

try {
// 默认 underfind 开启动画
if (animation === false) return;
const matrix = transform([['t', waveLength, 0]]);

Expand Down Expand Up @@ -369,6 +375,14 @@ function rect(x: number, y: number, width: number, height: number) {
`;
}

const builtInShapeByName = {
pin,
circle,
diamond,
triangle,
rect,
};

registerShape('interval', 'liquid-fill-gauge', {
draw(cfg: any, container: IGroup) {
const cx = 0.5;
Expand Down Expand Up @@ -399,13 +413,7 @@ registerShape('interval', 'liquid-fill-gauge', {
const waveAttrs = getFillAttrs(cfg);
const outlineAttrs = getLineAttrs(mix({}, cfg, outline));
const innerRadius = radius - border / 2;
const builtInShapeByName = {
pin,
circle,
diamond,
triangle,
rect,
};

const buildPath = typeof shape === 'function' ? shape : builtInShapeByName[shape] || builtInShapeByName['circle'];
const shapePath = buildPath(center.x, center.y, innerRadius * 2, innerRadius * 2);

Expand Down