@antv/g2
Version:
the Grammar of Graphics in Javascript
113 lines (99 loc) • 2.66 kB
text/typescript
import { deepMix, isArray } from '@antv/util';
import { stratify, hierarchy, pack as packLayout } from 'd3-hierarchy';
import { CompositionComponent as CC } from '../runtime';
import { subObject } from '../utils/helper';
import { PackMark } from '../spec';
import { maybeTooltip } from '../utils/mark';
import { field } from './utils';
const GET_DEFAULT_LAYOUT_OPTIONS = (width, height) => ({
size: [width, height],
padding: 0,
sort: (a, b) => b.value - a.value,
});
const GET_DEFAULT_OPTIONS = (width, height, encode) => ({
type: 'point',
axis: false,
legend: false,
scale: {
x: { domain: [0, width] },
y: { domain: [0, height] },
size: { type: 'identity' },
},
encode: {
x: 'x',
y: 'y',
size: 'r',
shape: 'point',
},
style: {
fill: !encode.color ? (d) => (d.height === 0 ? '#ddd' : '#fff') : undefined,
stroke: !encode.color ? (d) => (d.height === 0 ? '' : '#000') : undefined,
},
});
const DEFAULT_LABEL_OPTIONS = {
text: '',
position: 'inside',
textOverflow: 'clip',
wordWrap: true,
maxLines: 1,
wordWrapWidth: (d) => d.r * 2,
};
const DEFAULT_TOOLTIP_OPTIONS = {
title: (d) => d.data.name,
items: [{ field: 'value' }],
};
type PackLayout = {
size?: [number, number];
padding?: number;
sort?(a: any, b: any): number;
// @todo
path?: any;
};
const dataTransform = (data, layout: PackLayout, encode) => {
const { value } = encode;
const root = isArray(data)
? stratify().path(layout.path)(data)
: hierarchy(data);
value ? root.sum((d) => field(value)(d)).sort(layout.sort) : root.count();
// @ts-ignore
packLayout().size(layout.size).padding(layout.padding)(root);
return root.descendants();
};
export type PackOptions = Omit<PackMark, 'type'>;
export const Pack: CC<PackOptions> = (markOptions, context) => {
const { width, height } = context;
const {
data,
encode = {},
scale = {},
style = {},
layout = {},
labels = [],
tooltip = {},
...resOptions
} = markOptions;
const DEFAULT_OPTIONS = GET_DEFAULT_OPTIONS(width, height, encode);
const transformedData = dataTransform(
data,
deepMix({}, GET_DEFAULT_LAYOUT_OPTIONS(width, height), layout),
deepMix({}, DEFAULT_OPTIONS['encode'], encode),
);
const labelStyle = subObject(style, 'label');
return deepMix({}, DEFAULT_OPTIONS, {
data: transformedData,
encode,
scale,
style,
labels: [
{
...DEFAULT_LABEL_OPTIONS,
...labelStyle,
},
...labels,
],
...resOptions,
tooltip: maybeTooltip(tooltip, DEFAULT_TOOLTIP_OPTIONS),
axis: false,
});
};
Pack.props = {};