Skip to content

Commit

Permalink
feat(pie): optimize spider
Browse files Browse the repository at this point in the history
  • Loading branch information
pearmini committed Jul 12, 2024
1 parent bf13fe8 commit 80ad2a0
Show file tree
Hide file tree
Showing 9 changed files with 3,161 additions and 35 deletions.
1,504 changes: 1,504 additions & 0 deletions __tests__/integration/snapshots/static/mockPieSpider.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,504 changes: 1,504 additions & 0 deletions __tests__/integration/snapshots/static/mockPieSpiderRight.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions __tests__/plots/static/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,5 @@ export { stackBarAnnotationStyleText } from './stack-bar-annotation-style-text';
export { githubStarIntervalDarkThemeTransparent } from './github-star-interval-dark-theme-transparent';
export { diamondIntervalGroupX } from './diamond-interval-group-x';
export { mockIntervalSeriesOrder } from './mock-interval-series-order';
export { mockPieSpider } from './mock-pie-spider';
export { mockPieSpiderRight } from './mock-pie-spider-right';
32 changes: 32 additions & 0 deletions __tests__/plots/static/mock-pie-spider-right.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { G2Spec } from '../../../src';

export function mockPieSpiderRight(): G2Spec {
return {
type: 'interval',
data: [
{ type: '微博', value: 93.33 },
{ type: '其他', value: 6.67 },
{ type: '论坛', value: 4.77 },
{ type: '网站', value: 1.44 },
{ type: '微信', value: 1.12 },
{ type: '客户端', value: 1.05 },
{ type: '新闻', value: 0.81 },
{ type: '视频', value: 0.39 },
{ type: '博客', value: 0.37 },
{ type: '报刊', value: 0.17 },
].reverse(),
encode: {
y: 'value',
color: 'type',
},
labels: [
{
position: 'spider',
text: (obj) => `${obj.type} (${obj.value})`,
labelHeight: 30,
},
],
transform: [{ type: 'stackY' }],
coordinate: { type: 'theta' },
};
}
31 changes: 31 additions & 0 deletions __tests__/plots/static/mock-pie-spider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { G2Spec } from '../../../src';

export function mockPieSpider(): G2Spec {
return {
type: 'interval',
data: [
{ type: '微博', value: 93.33 },
{ type: '其他', value: 6.67 },
{ type: '论坛', value: 4.77 },
{ type: '网站', value: 1.44 },
{ type: '微信', value: 1.12 },
{ type: '客户端', value: 1.05 },
{ type: '新闻', value: 0.81 },
{ type: '视频', value: 0.39 },
{ type: '博客', value: 0.37 },
{ type: '报刊', value: 0.17 },
],
encode: {
y: 'value',
color: 'type',
},
labels: [
{
position: 'spider',
text: (obj) => `${obj.type} (${obj.value})`,
},
],
transform: [{ type: 'stackY' }],
coordinate: { type: 'theta' },
};
}
7 changes: 4 additions & 3 deletions src/shape/label/label.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ function getDefaultStyle(
coordinate: Coordinate,
theme: G2Theme,
options: LabelOptions,
labels: Vector2[][],
): Record<string, any> {
// For non-series mark, calc position for label based on
// position and the bounds of shape.
Expand All @@ -48,7 +49,7 @@ function getDefaultStyle(
}
return {
...t,
...processor(p, points, v, coordinate, options),
...processor(p, points, v, coordinate, options, labels),
};
}

Expand All @@ -59,7 +60,7 @@ function getDefaultStyle(
export const Label: SC<LabelOptions> = (options, context) => {
const { coordinate, theme } = context;
const { render } = options;
return (points, value) => {
return (points, value, style, labels) => {
const {
text,
x,
Expand All @@ -73,7 +74,7 @@ export const Label: SC<LabelOptions> = (options, context) => {
rotate = 0,
transform = '',
...defaultStyle
} = getDefaultStyle(points, value, coordinate, theme, options);
} = getDefaultStyle(points, value, coordinate, theme, options, labels);

return select(new Advance())
.call(applyStyle, defaultStyle)
Expand Down
54 changes: 44 additions & 10 deletions src/shape/label/position/spider.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import { Coordinate } from '@antv/coord';
import { sort } from 'd3-array';
import { Vector2 } from '../../../runtime';
import { isCircular } from '../../../utils/coordinate';
import { LabelPosition } from './default';
import { inferOutsideCircularStyle, radiusOf, angleOf } from './outside';

/**
* Spider label transform only suitable for the labels in polar coordinate, labels should distinguish coordinate type.
*/
export function spider(
position: LabelPosition,
const styleByPoints = new WeakMap();

function compute(
points: Vector2[],
value: Record<string, any>,
coordinate: Coordinate,
) {
if (!isCircular(coordinate)) return {};
const { connectorLength, connectorLength2, connectorDistance } = value;

const { ...style }: any = inferOutsideCircularStyle(
'outside',
points,
Expand All @@ -27,13 +24,50 @@ export function spider(
const angle = angleOf(points, value, coordinate);
const radius1 = radius + connectorLength + connectorLength2;
const sign = Math.sin(angle) > 0 ? 1 : -1;

const newX = center[0] + (radius1 + +connectorDistance) * sign;

const { x: originX } = style;
const dx = newX - originX;
style.x += dx;
style.connectorPoints[0][0] -= dx;

return style;
}

function dodgeY(
styles: Record<string, any>[],
options: Record<string, any> = {},
) {
const { labelHeight = 15 } = options;
const sortedStyles = sort(styles, (d) => d.y);
let preY = -labelHeight;
for (let i = 0; i < sortedStyles.length; ++i) {
const cur = sortedStyles[i];
const nextY = preY + labelHeight;
const dy = Math.max(0, nextY - cur.y);
cur.labelOffsetY = dy;
preY = cur.y + dy;
}
}

/**
* Spider label transform only suitable for the labels in polar coordinate,
* labels should distinguish coordinate type.
*/
export function spider(
position: LabelPosition,
points: Vector2[],
value: Record<string, any>,
coordinate: Coordinate,
options: Record<string, any>,
labels: Vector2[][],
) {
if (!isCircular(coordinate)) return {};
if (styleByPoints.has(points)) return styleByPoints.get(points);
const styles = labels.map((points) => compute(points, value, coordinate));
const { width } = coordinate.getOptions();
const left = styles.filter((d) => d.x < width / 2);
const right = styles.filter((d) => d.x >= width / 2);
dodgeY(left, options);
dodgeY(right, options);
styles.forEach((style, i) => styleByPoints.set(labels[i], style));
return styleByPoints.get(points);
}
Loading

0 comments on commit 80ad2a0

Please sign in to comment.