diff --git a/packages/plots/src/components/index.ts b/packages/plots/src/components/index.ts index 1044a9f7d0..2b8b30c8d5 100644 --- a/packages/plots/src/components/index.ts +++ b/packages/plots/src/components/index.ts @@ -22,6 +22,8 @@ import WordCloud from './wordCloud'; import Treemap from './treemap'; import Violin from './violin'; import BidirectionalBar from './bidirectional-bar'; +import Venn from './venn'; + export type { AreaConfig } from './area'; export type { BarConfig } from './bar'; @@ -46,6 +48,8 @@ export type { WordCloudConfig } from './wordCloud'; export type { TreemapConfig } from './treemap'; export type { ViolinConfig } from './violin'; export type { BidirectionalBarConfig } from './bidirectional-bar'; +export type { VennConfig } from './venn'; + export { Base, @@ -72,4 +76,5 @@ export { Treemap, Violin, BidirectionalBar, + Venn }; diff --git a/packages/plots/src/components/venn/index.tsx b/packages/plots/src/components/venn/index.tsx new file mode 100644 index 0000000000..3bf2e9e04c --- /dev/null +++ b/packages/plots/src/components/venn/index.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { VennOptions } from '../../core'; +import { CommonConfig } from '../../interface'; +import { BaseChart } from '../base'; + +export type VennConfig = CommonConfig; + +const VennChart = (props: VennConfig) => ; + +export default VennChart; diff --git a/packages/plots/src/core/index.ts b/packages/plots/src/core/index.ts index 514ce3f7e8..2ad3037b58 100644 --- a/packages/plots/src/core/index.ts +++ b/packages/plots/src/core/index.ts @@ -26,6 +26,8 @@ export type { WordCloudOptions } from './plots/wordCloud'; export type { TreemapOptions } from './plots/treemap'; export type { ViolinOptions } from './plots/violin'; export type { BidirectionalBarOptions } from './plots/bidirectional-bar'; +export type { VennOptions } from './plots/venn'; + export * from './types'; import { Base } from './plots/base'; @@ -56,6 +58,7 @@ import { WordCloud } from './plots/wordCloud'; import { Treemap } from './plots/treemap'; import { Violin } from './plots/violin'; import { BidirectionalBar } from './plots/bidirectional-bar'; +import { Venn } from './plots/venn'; export const Plots = { Base, @@ -86,4 +89,5 @@ export const Plots = { Treemap, Violin, BidirectionalBar, + Venn, }; diff --git a/packages/plots/src/core/plots/venn/adaptor.ts b/packages/plots/src/core/plots/venn/adaptor.ts new file mode 100644 index 0000000000..df6718731b --- /dev/null +++ b/packages/plots/src/core/plots/venn/adaptor.ts @@ -0,0 +1,90 @@ +import { flow, isArray, omit, remove, set, transformOptions } from '../../utils'; +import { mark } from '../../components'; +import type { Adaptor } from '../../types'; +import { DefaultTransformKey, type VennOptions } from './type'; + +type Params = Adaptor; + +/** + * @param chart + * @param options + */ +export function adaptor(params: Params) { + /** + * 图表差异化处理 + */ + const init = (params: Params) => { + const { options } = params; + const { data, setsField, sizeField } = options; + if (isArray(data)) { + set(options, 'data', { + type: 'inline', + value: data, + transform: [ + { + type: 'venn', + sets: setsField, + size: sizeField, + as: [DefaultTransformKey.color, DefaultTransformKey.d], + }, + ], + }); + set(options, 'colorField', setsField); + set(options?.children[0]?.encode, 'd', sizeField); + } + set(params, 'options', omit(options, ['sizeField', 'setsField'])); + return params; + }; + + // const dField = (params: Params) => { + // const { options } = params; + // const { setsField } = options; + // // set(options?.children[0]?.encode, 'd', 'sets'); + // // set(options?.children[0], 'encode', omit(options?.children[0]?.encode, ['size'])); + + // return params; + // }; + + // const color = (params: Params) => { + // const { options } = params; + // set(options, 'colorField', 'key'); + // return params; + // }; + + const style = (params: Params) => { + const { options } = params; + const { pointStyle, style } = options; + set(options, 'style', { ...style, ...pointStyle }); + set(params, 'options', omit(options, ['pointStyle'])); + return params; + }; + + // const tooltip = (params) => { + // const { options } = params; + // const { tooltip } = options; + // if (!tooltip) { + // set(options, 'tooltip', { + // title: false, + // items: [ + // (d) => { + // return { name: d.key, value: d.size }; + // }, + // ], + // }); + // } + // return params; + // }; + + const transformColorRange = (params: Params) => { + const { options } = params; + const { color } = options; + if (color) { + set(options, 'scale', { + color: { range: color }, + }); + } + return params; + }; + + return flow(init, style, transformColorRange, transformOptions)(params); +} diff --git a/packages/plots/src/core/plots/venn/index.ts b/packages/plots/src/core/plots/venn/index.ts new file mode 100644 index 0000000000..a985b8bdd9 --- /dev/null +++ b/packages/plots/src/core/plots/venn/index.ts @@ -0,0 +1,69 @@ +import { Plot } from '../../base'; +import type { Adaptor } from '../../types'; +import { adaptor } from './adaptor'; +import { DefaultTransformKey, VennOptions } from './type'; + +export type { VennOptions }; + +export class Venn extends Plot { + /** 图表类型 */ + public type = 'venn'; + + /** + * 获取 折线图 默认配置项 + * 供外部使用 + */ + static getDefaultOptions(): Partial { + return { + type: 'view', + children: [{ type: 'path' }], + label: { + position: 'inside', + text: (d) => d.label || '', + }, + legend: { + color: { itemMarker: 'circle' }, + }, + // colorField: 'key', + tooltip: { + title: false, + items: [ + (d) => { + return { name: d.key, value: d.size }; + }, + ], + }, + encode: { color: DefaultTransformKey.color, d: DefaultTransformKey.d }, + // colorField: 'sets', + // scale: { + // y: { nice: true }, + // }, + // interaction: { + // tooltip: { + // shared: true, + // }, + // }, + // axis: { + // y: { title: false }, + // x: { title: false }, + // }, + // animate: { + // enter: { type: 'growInX' }, + // }, + }; + } + + /** + * 获取 折线图 默认配置 + */ + protected getDefaultOptions() { + return Venn.getDefaultOptions(); + } + + /** + * 折线图适配器 + */ + protected getSchemaAdaptor(): (params: Adaptor) => void { + return adaptor; + } +} diff --git a/packages/plots/src/core/plots/venn/type.ts b/packages/plots/src/core/plots/venn/type.ts new file mode 100644 index 0000000000..002c6a72da --- /dev/null +++ b/packages/plots/src/core/plots/venn/type.ts @@ -0,0 +1,8 @@ +import type { BaseOptions, Options } from '../../types/common'; + +export type VennOptions = Options & BaseOptions; + +export enum DefaultTransformKey { + color = 'key', + d = 'path', +} diff --git a/site/examples/statistics/venn/demo/basic.js b/site/examples/statistics/venn/demo/basic.js new file mode 100644 index 0000000000..121f2282ba --- /dev/null +++ b/site/examples/statistics/venn/demo/basic.js @@ -0,0 +1,23 @@ +import { Venn } from '@ant-design/plots'; +import React from 'react'; +import ReactDOM from 'react-dom'; + +const DemoVenn = () => { + const config = { + data: [ + { sets: ['A'], size: 12, label: 'A' }, + { sets: ['B'], size: 12, label: 'B' }, + { sets: ['C'], size: 12, label: 'C' }, + { sets: ['A', 'B'], size: 2, label: 'A&B' }, + { sets: ['A', 'C'], size: 2, label: 'A&C' }, + { sets: ['B', 'C'], size: 2, label: 'B&C' }, + { sets: ['A', 'B', 'C'], size: 1 }, + ], + setsField: 'sets', + sizeField: 'size', + pointStyle: { fillOpacity: 0.85 }, + }; + return ; +}; + +ReactDOM.render(, document.getElementById('container')); diff --git a/site/examples/statistics/venn/demo/custom-color.js b/site/examples/statistics/venn/demo/custom-color.js new file mode 100644 index 0000000000..7a2c681944 --- /dev/null +++ b/site/examples/statistics/venn/demo/custom-color.js @@ -0,0 +1,30 @@ +import { Venn } from '@ant-design/plots'; +import React from 'react'; +import ReactDOM from 'react-dom'; + +const DemoVenn = () => { + const config = { + data: [ + { sets: ['A'], size: 12, label: 'A' }, + { sets: ['B'], size: 12, label: 'B' }, + { sets: ['C'], size: 12, label: 'C' }, + { sets: ['A', 'B'], size: 2, label: 'A&B' }, + { sets: ['A', 'C'], size: 2, label: 'A&C' }, + { sets: ['B', 'C'], size: 2, label: 'B&C' }, + { sets: ['A', 'B', 'C'], size: 1 }, + ], + setsField: 'sets', + sizeField: 'size', + pointStyle: { fillOpacity: 0.85 }, + style: { + fill: (datum, index, data) => { + console.log(data) + const { size } = datum; + if (size <= 2) return '#f4bb51'; + }, + }, + }; + return ; +}; + +ReactDOM.render(, document.getElementById('container')); diff --git a/site/examples/statistics/venn/demo/custom.js b/site/examples/statistics/venn/demo/custom.js new file mode 100644 index 0000000000..d7dc7ff278 --- /dev/null +++ b/site/examples/statistics/venn/demo/custom.js @@ -0,0 +1,47 @@ +import { Venn } from '@ant-design/plots'; +import React from 'react'; +import ReactDOM from 'react-dom'; + +const DemoVenn = () => { + const config = { + data: { + type: 'fetch', + value: 'https://gw.alipayobjects.com/os/bmw-prod/c4c17fe9-0a93-4255-bc1e-1ff84966d24a.json', + transform: [ + { + type: 'venn', + sets: 'sets', + size: 'size', + as: ['key', 'path'], + }, + ], + }, + setsField: 'sets', + sizeField: 'size', + pointStyle: { fillOpacity: 0.85 }, + color: ['#9DF5CA', '#61DDAA', '#42C090'], + label: { + style: { + lineHeight: 20, + }, + text: (datum) => { + return `${datum.size}`; + }, + }, + interaction: { + tooltip: { + // render 回调方法返回一个innerHTML 或者 DOM + render: (event, { title, items }) => { + console.log(event, { title, items }); + return `
+

title:${title}

+
    ${items.map((d) => `
  • ${d.name} ${d.value}
  • `)}
+
`; + }, + }, + }, + }; + return ; +}; + +ReactDOM.render(, document.getElementById('container')); diff --git a/site/examples/statistics/venn/demo/interaction.js b/site/examples/statistics/venn/demo/interaction.js new file mode 100644 index 0000000000..5582e6efae --- /dev/null +++ b/site/examples/statistics/venn/demo/interaction.js @@ -0,0 +1,37 @@ +import { Venn } from '@ant-design/plots'; +import React from 'react'; +import ReactDOM from 'react-dom'; + +const DemoVenn = () => { + const config = { + data: [ + { sets: ['A'], size: 12, label: 'A' }, + { sets: ['B'], size: 12, label: 'B' }, + { sets: ['C'], size: 12, label: 'C' }, + { sets: ['A', 'B'], size: 2, label: 'A&B' }, + { sets: ['A', 'C'], size: 2, label: 'A&C' }, + { sets: ['B', 'C'], size: 2, label: 'B&C' }, + { sets: ['A', 'B', 'C'], size: 1 }, + ], + setsField: 'sets', + sizeField: 'size', + pointStyle: { fillOpacity: 0.85 }, + state: { + active: { + fillOpacity: 0.8, + stroke: 'red', + lineWidth: 1, + }, + inactive: { + fillOpacity: 0.2, + lineWidth: 0, + }, + }, + interaction: { + elementHighlight: true, + }, + }; + return ; +}; + +ReactDOM.render(, document.getElementById('container')); diff --git a/site/examples/statistics/venn/demo/label.js b/site/examples/statistics/venn/demo/label.js new file mode 100644 index 0000000000..26cb37958e --- /dev/null +++ b/site/examples/statistics/venn/demo/label.js @@ -0,0 +1,28 @@ +import { Venn } from '@ant-design/plots'; +import React from 'react'; +import ReactDOM from 'react-dom'; + +const DemoVenn = () => { + const config = { + data: [ + { sets: ['A'], size: 12, label: 'A' }, + { sets: ['B'], size: 12, label: 'B' }, + { sets: ['C'], size: 12, label: 'C' }, + { sets: ['A', 'B'], size: 2, label: 'A&B' }, + { sets: ['A', 'C'], size: 2, label: 'A&C' }, + { sets: ['B', 'C'], size: 2, label: 'B&C' }, + { sets: ['A', 'B', 'C'], size: 1 }, + ], + setsField: 'sets', + sizeField: 'size', + pointStyle: { fillOpacity: 0.85 }, + label: { + position: 'inside', + text: (d) => d.label || '', + transform: [{ type: 'contrastReverse' }], + } + }; + return ; +}; + +ReactDOM.render(, document.getElementById('container')); diff --git a/site/examples/statistics/venn/demo/meta.json b/site/examples/statistics/venn/demo/meta.json new file mode 100644 index 0000000000..0c6f4501a6 --- /dev/null +++ b/site/examples/statistics/venn/demo/meta.json @@ -0,0 +1,57 @@ +{ + "title": { + "zh": "中文分类", + "en": "Category" + }, + "demos": [ + { + "filename": "basic.js", + "title": { + "zh": "基础韦恩图", + "en": "Basic venn plot" + }, + "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/BJw8fy6uxU/009dd50e-c2a4-48dc-a79a-dc417123889f.png" + }, + { + "filename": "custom-color.js", + "title": { + "zh": "自定义颜色", + "en": "Custom color" + }, + "screenshot": "https://mdn.alipayobjects.com/huamei_lwk8lu/afts/img/A*zLutTqj3As0AAAAAAAAAAAAADma_AQ/original" + }, + + { + "filename": "tooltip.js", + "title": { + "zh": "格式化tooltip", + "en": "Formatter tooltip" + }, + "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/BJw8fy6uxU/009dd50e-c2a4-48dc-a79a-dc417123889f.png" + }, + { + "filename": "label.js", + "title": { + "zh": "设置label", + "en": "Label setting" + }, + "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/BJw8fy6uxU/009dd50e-c2a4-48dc-a79a-dc417123889f.png" + }, + { + "filename": "custom.js", + "title": { + "zh": "自定义韦恩图", + "en": "Customize venn plot" + }, + "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/T6cgHx5BHB/f2137e3b-5784-4626-a986-109fc8cb5feb.png" + }, + { + "filename": "interaction.js", + "title": { + "zh": "韦恩图-元素交互", + "en": "venn plot - with element action" + }, + "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/BJw8fy6uxU/009dd50e-c2a4-48dc-a79a-dc417123889f.png" + } + ] +} diff --git a/site/examples/statistics/venn/demo/tooltip.js b/site/examples/statistics/venn/demo/tooltip.js new file mode 100644 index 0000000000..463d6461ef --- /dev/null +++ b/site/examples/statistics/venn/demo/tooltip.js @@ -0,0 +1,24 @@ +import { Venn } from '@ant-design/plots'; +import React from 'react'; +import ReactDOM from 'react-dom'; + +const DemoVenn = () => { + const config = { + data: [ + { sets: ['A'], size: 12, label: 'A' }, + { sets: ['B'], size: 12, label: 'B' }, + { sets: ['C'], size: 12, label: 'C' }, + { sets: ['A', 'B'], size: 2, label: 'A&B' }, + { sets: ['A', 'C'], size: 2, label: 'A&C' }, + { sets: ['B', 'C'], size: 2, label: 'B&C' }, + { sets: ['A', 'B', 'C'], size: 1 }, + ], + setsField: 'sets', + sizeField: 'size', + pointStyle: { fillOpacity: 0.85 }, + tooltip: { items: [(d) => ({ name: d.key, value: d.size })] }, + }; + return ; +}; + +ReactDOM.render(, document.getElementById('container')); diff --git a/site/examples/statistics/venn/index.en.md b/site/examples/statistics/venn/index.en.md new file mode 100644 index 0000000000..811ec7aabd --- /dev/null +++ b/site/examples/statistics/venn/index.en.md @@ -0,0 +1,4 @@ +--- +title: Venn +order: 3 +--- diff --git a/site/examples/statistics/venn/index.zh.md b/site/examples/statistics/venn/index.zh.md new file mode 100644 index 0000000000..584b58f516 --- /dev/null +++ b/site/examples/statistics/venn/index.zh.md @@ -0,0 +1,6 @@ +--- +title: 韦恩图 +order: 3 +--- + +