@antv/g2plot
Version:
An interactive and responsive charting library
231 lines (207 loc) • 5.81 kB
text/typescript
import { get } from '@antv/util';
import { Types } from '@antv/g2';
import { point } from '../../adaptor/geometries/point';
import { Params } from '../../core/adaptor';
import {
interaction as baseInteraction,
animation,
theme,
legend,
annotation,
scale,
pattern,
} from '../../adaptor/common';
import { flow, deepAssign } from '../../utils';
import { getAdjustAppendPadding, resolveAllPadding } from '../../utils/padding';
import { transformData, resolvePaddingForCircle } from './utils';
import { CirclePackingOptions } from './types';
import { RAW_FIELDS } from './constant';
/**
* 获取默认 option
* @param params
*/
function defaultOptions(params: Params<CirclePackingOptions>): Params<CirclePackingOptions> {
const { chart } = params;
const diameter = Math.min(chart.viewBBox.width, chart.viewBBox.height);
return deepAssign(
{
options: {
size: ({ r }) => r * diameter, // 当autofit:false时,默认给固定半径
},
},
params
);
}
/**
* padding 配置
* @param params
*/
function padding(params: Params<CirclePackingOptions>): Params<CirclePackingOptions> {
const { options, chart } = params;
// 通过改变 padding,修改 coordinate 的绘制区域
const containerSize = chart.viewBBox;
const { padding, appendPadding, drilldown } = options;
let tempAppendPadding = appendPadding;
if (drilldown?.enabled) {
const appendPaddingByDrilldown = getAdjustAppendPadding(
chart.appendPadding,
get(drilldown, ['breadCrumb', 'position'])
);
tempAppendPadding = resolveAllPadding([appendPaddingByDrilldown, appendPadding]);
}
const { finalPadding } = resolvePaddingForCircle(padding, tempAppendPadding, containerSize);
chart.padding = finalPadding;
chart.appendPadding = 0;
return params;
}
/**
* 字段
* @param params
*/
function geometry(params: Params<CirclePackingOptions>): Params<CirclePackingOptions> {
const { chart, options } = params;
const { padding, appendPadding } = chart;
const { color, colorField, pointStyle, hierarchyConfig, sizeField, rawFields = [], drilldown } = options;
const data = transformData({
data: options.data,
hierarchyConfig,
enableDrillDown: drilldown?.enabled,
rawFields,
});
chart.data(data);
const containerSize = chart.viewBBox;
const { finalSize } = resolvePaddingForCircle(padding, appendPadding, containerSize);
// 有sizeField的时候,例如 value ,可以选择映射 size 函数,自己计算出映射的半径
let circleSize = ({ r }) => r * finalSize; // 默认配置
if (sizeField) {
circleSize = (d) => d[sizeField] * finalSize; // 目前只有 r 通道映射效果会正常
}
// geometry
point(
deepAssign({}, params, {
options: {
xField: 'x',
yField: 'y',
seriesField: colorField,
sizeField,
rawFields: [...RAW_FIELDS, ...rawFields],
point: {
color,
style: pointStyle,
shape: 'circle',
size: circleSize,
},
},
})
);
return params;
}
/**
* meta 配置
* @param params
*/
export function meta(params: Params<CirclePackingOptions>): Params<CirclePackingOptions> {
return flow(
scale(
{},
{
// 必须强制为 nice
x: { min: 0, max: 1, minLimit: 0, maxLimit: 1, nice: true },
y: { min: 0, max: 1, minLimit: 0, maxLimit: 1, nice: true },
}
)
)(params);
}
/**
* tooltip 配置
* @param params
*/
function tooltip(params: Params<CirclePackingOptions>): Params<CirclePackingOptions> {
const { chart, options } = params;
const { tooltip } = options;
if (tooltip === false) {
chart.tooltip(false);
} else {
let tooltipOptions = tooltip;
// 设置了 fields,就不进行 customItems 了; 设置 formatter 时,需要搭配 fields
if (!get(tooltip, 'fields')) {
tooltipOptions = deepAssign(
{},
{
customItems: (items: Types.TooltipItem[]) =>
items.map((item) => {
const scales = get(chart.getOptions(), 'scales');
const nameFormatter = get(scales, ['name', 'formatter'], (v) => v);
const valueFormatter = get(scales, ['value', 'formatter'], (v) => v);
return {
...item,
name: nameFormatter(item.data.name),
value: valueFormatter(item.data.value),
};
}),
},
tooltipOptions
);
}
chart.tooltip(tooltipOptions);
}
return params;
}
/**
* 坐标轴, 默认关闭
* @param params
*/
function axis(params: Params<CirclePackingOptions>): Params<CirclePackingOptions> {
const { chart } = params;
chart.axis(false);
return params;
}
function adaptorInteraction(options: CirclePackingOptions): CirclePackingOptions {
const { drilldown, interactions = [] } = options;
if (drilldown?.enabled) {
return deepAssign({}, options, {
interactions: [
...interactions,
{
type: 'drill-down',
cfg: { drillDownConfig: drilldown, transformData, enableDrillDown: true },
},
],
});
}
return options;
}
/**
* 交互配置
* @param params
* @returns
*/
function interaction(params: Params<CirclePackingOptions>): Params<CirclePackingOptions> {
const { chart, options } = params;
baseInteraction({
chart,
options: adaptorInteraction(options),
});
return params;
}
/**
* 矩形树图
* @param chart
* @param options
*/
export function adaptor(params: Params<CirclePackingOptions>) {
return flow(
pattern('pointStyle'),
defaultOptions,
padding,
theme,
meta,
geometry,
axis,
legend,
tooltip,
interaction,
animation,
annotation()
)(params);
}