mirror of
https://gitee.com/antv/g6.git
synced 2024-12-01 19:28:39 +08:00
feat: add demo about why do cats (#6259)
* test: add demo of why do cats * docs: add site demo * docs: add demo ref --------- Co-authored-by: antv <antv@antfin.com>
This commit is contained in:
parent
6317115603
commit
b00ec104f8
@ -30,6 +30,8 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antv/g-canvas": "^2.0.10",
|
||||
"@antv/g-plugin-rough-canvas-renderer": "^2.0.12",
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/plugin-transform-typescript": "^7.25.2",
|
||||
"@changesets/cli": "^2.27.7",
|
||||
@ -42,12 +44,14 @@
|
||||
"@rollup/plugin-typescript": "^11.1.6",
|
||||
"@swc/core": "^1.7.6",
|
||||
"@swc/jest": "^0.2.36",
|
||||
"@types/d3-hierarchy": "^3.1.7",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"@types/node": "^20.14.14",
|
||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||
"@typescript-eslint/parser": "^6.21.0",
|
||||
"chalk": "^4.1.2",
|
||||
"d3-hierarchy": "^3.1.2",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-jsdoc": "^46.10.1",
|
||||
"husky": "^8.0.3",
|
||||
|
189
packages/g6/__tests__/demos/case-why-do-cats.ts
Normal file
189
packages/g6/__tests__/demos/case-why-do-cats.ts
Normal file
@ -0,0 +1,189 @@
|
||||
import { Renderer as CanvasRenderer } from '@antv/g-canvas';
|
||||
import { Plugin as PluginRoughCanvasRenderer } from '@antv/g-plugin-rough-canvas-renderer';
|
||||
import type { ComboData, GraphData, NodeData } from '@antv/g6';
|
||||
import { BaseLayout, ExtensionCategory, Graph, register } from '@antv/g6';
|
||||
import { hierarchy, pack } from 'd3-hierarchy';
|
||||
|
||||
export const caseWhyDoCats: TestCase = async (context) => {
|
||||
const style = document.createElement('style');
|
||||
style.innerHTML = `
|
||||
@font-face {
|
||||
font-family: 'handwriting';
|
||||
src: url('https://mass-office.alipay.com/huamei_koqzbu/afts/file/sgUeRbI3d-IAAAAAAAAAABAADnV5AQBr/font.woff2')
|
||||
format('woff2');
|
||||
}`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
function getColor(id: string) {
|
||||
const colors = [
|
||||
'#8dd3c7',
|
||||
'#bebada',
|
||||
'#fb8072',
|
||||
'#80b1d3',
|
||||
'#fdb462',
|
||||
'#b3de69',
|
||||
'#fccde5',
|
||||
'#d9d9d9',
|
||||
'#bc80bd',
|
||||
'#ccebc5',
|
||||
'#ffed6f',
|
||||
];
|
||||
const index = parseInt(id);
|
||||
return colors[index % colors.length];
|
||||
}
|
||||
|
||||
type RowDatum = {
|
||||
animal: string;
|
||||
id: string;
|
||||
id_num: string;
|
||||
index_value: string;
|
||||
leaf: string;
|
||||
parentId: string;
|
||||
remainder: string;
|
||||
start_sentence: string;
|
||||
sum_index_value: string;
|
||||
text: string;
|
||||
};
|
||||
|
||||
const rawData: RowDatum[] = await fetch('https://assets.antv.antgroup.com/g6/cat-hierarchy.json').then((res) =>
|
||||
res.json(),
|
||||
);
|
||||
|
||||
const topics = [
|
||||
'cat.like',
|
||||
'cat.hate',
|
||||
'cat.love',
|
||||
'cat.not.like',
|
||||
'cat.afraid_of',
|
||||
'cat.want.to',
|
||||
'cat.scared.of',
|
||||
'cat.not.want_to',
|
||||
];
|
||||
|
||||
const graphData = rawData.reduce(
|
||||
(acc, row) => {
|
||||
const { id } = row;
|
||||
topics.forEach((topic) => {
|
||||
if (id.startsWith(topic)) {
|
||||
if (id === topic) {
|
||||
acc.nodes.push({ ...row, depth: 1 });
|
||||
} else {
|
||||
acc.nodes.push({ ...row, depth: 2, actualParentId: topic });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return acc;
|
||||
},
|
||||
{ nodes: [], edges: [], combos: [] } as Required<GraphData>,
|
||||
);
|
||||
|
||||
class BubbleLayout extends BaseLayout {
|
||||
id = 'bubble-layout';
|
||||
|
||||
public async execute(model: GraphData, options?: any): Promise<GraphData> {
|
||||
const { nodes = [] } = model;
|
||||
|
||||
const { width = 0, height = 0 } = { ...this.options, ...options };
|
||||
|
||||
const root = hierarchy<NodeData | ComboData>({ id: 'root' }, (datum) => {
|
||||
const { id } = datum;
|
||||
if (id === 'root') return nodes.filter((node) => node.depth === 1);
|
||||
else if (datum.depth === 2) return [];
|
||||
else return nodes.filter((node) => node.actualParentId === id);
|
||||
});
|
||||
|
||||
root.sum((d: any) => (+d.index_value || 0.01) ** 0.5 * 100);
|
||||
|
||||
pack<NodeData | ComboData>()
|
||||
.size([width, height])
|
||||
.padding((node) => {
|
||||
return node.depth === 0 ? 20 : 2;
|
||||
})(root);
|
||||
|
||||
const result: Required<GraphData> = { nodes: [], edges: [], combos: [] };
|
||||
|
||||
root.descendants().forEach((node) => {
|
||||
const {
|
||||
data: { id },
|
||||
x,
|
||||
y,
|
||||
// @ts-expect-error r is exist
|
||||
r,
|
||||
} = node;
|
||||
|
||||
if (node.depth >= 1) result.nodes.push({ id, style: { x, y, size: r * 2 } });
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
register(ExtensionCategory.LAYOUT, 'bubble-layout', BubbleLayout);
|
||||
|
||||
const graph = new Graph({
|
||||
...context,
|
||||
animation: false,
|
||||
data: graphData,
|
||||
renderer: (layer) => {
|
||||
const renderer = new CanvasRenderer();
|
||||
if (layer === 'main') {
|
||||
renderer.registerPlugin(new PluginRoughCanvasRenderer());
|
||||
}
|
||||
return renderer;
|
||||
},
|
||||
node: {
|
||||
style: (d) => {
|
||||
const id_num = d.id_num as string;
|
||||
const color = getColor(id_num);
|
||||
|
||||
if (d.depth === 1) {
|
||||
return {
|
||||
fill: 'none',
|
||||
stroke: color,
|
||||
labelFontFamily: 'handwriting',
|
||||
labelFontSize: 20,
|
||||
labelText: d.id.replace('cat.', '').replace(/\.|_/g, ' '),
|
||||
labelTextTransform: 'capitalize',
|
||||
lineWidth: 1,
|
||||
zIndex: -1,
|
||||
};
|
||||
}
|
||||
|
||||
const text = d.text as string;
|
||||
const diameter = d.style!.size as number;
|
||||
|
||||
return {
|
||||
fill: color,
|
||||
fillOpacity: 0.7,
|
||||
stroke: color,
|
||||
fillStyle: 'cross-hatch',
|
||||
hachureGap: 1.5,
|
||||
iconFontFamily: 'handwriting',
|
||||
iconFontSize: (diameter / text.length) * 2,
|
||||
iconText: diameter > 20 ? d.text : '',
|
||||
iconFontWeight: 'bold',
|
||||
iconStroke: color,
|
||||
iconLineWidth: 2,
|
||||
lineWidth: (diameter || 20) ** 0.5 / 5,
|
||||
};
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'bubble-layout',
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
type: 'tooltip',
|
||||
getContent: (event: any, items: NodeData[]) => {
|
||||
return `<span style="text-transform: capitalize; font-family: handwriting; font-size: 20px;">${items[0].id.replace(/\.|_/g, ' ')}</span>`;
|
||||
},
|
||||
},
|
||||
],
|
||||
behaviors: [{ type: 'drag-canvas', enable: true }, 'zoom-canvas'],
|
||||
});
|
||||
|
||||
await graph.render();
|
||||
|
||||
return graph;
|
||||
};
|
@ -25,6 +25,7 @@ export { caseDecisionTree } from './case-decision-tree';
|
||||
export { caseIndentedTree } from './case-indented-tree';
|
||||
export { caseMindmap } from './case-mindmap';
|
||||
export { caseOrgChart } from './case-org-chart';
|
||||
export { caseWhyDoCats } from './case-why-do-cats';
|
||||
export { commonGraph } from './common-graph';
|
||||
export { controllerViewport } from './controller-viewport';
|
||||
export { demoAutosizeElementLabel } from './demo-autosize-element-label';
|
||||
|
@ -1019,6 +1019,7 @@ export class Graph extends EventEmitter {
|
||||
if (container instanceof Canvas) {
|
||||
this.context.canvas = container;
|
||||
if (cursor) container.setCursor(cursor);
|
||||
if (renderer) container.setRenderer(renderer);
|
||||
await container.ready;
|
||||
} else {
|
||||
const $container = isString(container) ? document.getElementById(container!) : container;
|
||||
|
@ -1,5 +1,9 @@
|
||||
// @ts-nocheck
|
||||
if (window) {
|
||||
window.d3Hierarchy = require('d3-hierarchy');
|
||||
window.gCanvas = require('@antv/g-canvas');
|
||||
window.gPluginRoughCanvasRenderer = require('@antv/g-plugin-rough-canvas-renderer');
|
||||
|
||||
window.g6 = require('@antv/g6');
|
||||
window.g6Extension3d = require('@antv/g6-extension-3d');
|
||||
window.g6ExtensionReact = require('@antv/g6-extension-react');
|
||||
|
@ -59,6 +59,14 @@
|
||||
"en": "Sub Graph"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*2HzDTrQZ910AAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "why-do-cats.js",
|
||||
"title": {
|
||||
"zh": "猫咪喜好",
|
||||
"en": "Why Do Cats?"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ug4vTJA7QbMAAAAAAAAAAAAADmJ7AQ/original"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
174
packages/site/examples/scene-case/default/demo/why-do-cats.js
Normal file
174
packages/site/examples/scene-case/default/demo/why-do-cats.js
Normal file
@ -0,0 +1,174 @@
|
||||
// ref: https://whydocatsanddogs.com/cats
|
||||
import { Renderer as CanvasRenderer } from '@antv/g-canvas';
|
||||
import { Plugin as PluginRoughCanvasRenderer } from '@antv/g-plugin-rough-canvas-renderer';
|
||||
import { BaseLayout, ExtensionCategory, Graph, register } from '@antv/g6';
|
||||
import { hierarchy, pack } from 'd3-hierarchy';
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.innerHTML = `
|
||||
@font-face {
|
||||
font-family: 'handwriting';
|
||||
src: url('https://mass-office.alipay.com/huamei_koqzbu/afts/file/sgUeRbI3d-IAAAAAAAAAABAADnV5AQBr/font.woff2')
|
||||
format('woff2');
|
||||
}`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
function getColor(id) {
|
||||
const colors = [
|
||||
'#8dd3c7',
|
||||
'#bebada',
|
||||
'#fb8072',
|
||||
'#80b1d3',
|
||||
'#fdb462',
|
||||
'#b3de69',
|
||||
'#fccde5',
|
||||
'#d9d9d9',
|
||||
'#bc80bd',
|
||||
'#ccebc5',
|
||||
'#ffed6f',
|
||||
];
|
||||
const index = parseInt(id);
|
||||
return colors[index % colors.length];
|
||||
}
|
||||
|
||||
const topics = [
|
||||
'cat.like',
|
||||
'cat.hate',
|
||||
'cat.love',
|
||||
'cat.not.like',
|
||||
'cat.afraid_of',
|
||||
'cat.want.to',
|
||||
'cat.scared.of',
|
||||
'cat.not.want_to',
|
||||
];
|
||||
|
||||
class BubbleLayout extends BaseLayout {
|
||||
id = 'bubble-layout';
|
||||
|
||||
async execute(model, options) {
|
||||
const { nodes = [] } = model;
|
||||
|
||||
const { width = 0, height = 0 } = { ...this.options, ...options };
|
||||
|
||||
const root = hierarchy({ id: 'root' }, (datum) => {
|
||||
const { id } = datum;
|
||||
if (id === 'root') return nodes.filter((node) => node.depth === 1);
|
||||
else if (datum.depth === 2) return [];
|
||||
else return nodes.filter((node) => node.actualParentId === id);
|
||||
});
|
||||
|
||||
root.sum((d) => (+d.index_value || 0.01) ** 0.5 * 100);
|
||||
|
||||
pack()
|
||||
.size([width, height])
|
||||
.padding((node) => {
|
||||
return node.depth === 0 ? 20 : 2;
|
||||
})(root);
|
||||
|
||||
const result = { nodes: [] };
|
||||
|
||||
root.descendants().forEach((node) => {
|
||||
const {
|
||||
data: { id },
|
||||
x,
|
||||
y,
|
||||
// @ts-expect-error r is exist
|
||||
r,
|
||||
} = node;
|
||||
|
||||
if (node.depth >= 1) result.nodes.push({ id, style: { x, y, size: r * 2 } });
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
register(ExtensionCategory.LAYOUT, 'bubble-layout', BubbleLayout);
|
||||
|
||||
fetch('https://assets.antv.antgroup.com/g6/cat-hierarchy.json')
|
||||
.then((res) => res.json())
|
||||
.then((rawData) => {
|
||||
const graphData = rawData.reduce(
|
||||
(acc, row) => {
|
||||
const { id } = row;
|
||||
topics.forEach((topic) => {
|
||||
if (id.startsWith(topic)) {
|
||||
if (id === topic) {
|
||||
acc.nodes.push({ ...row, depth: 1 });
|
||||
} else {
|
||||
acc.nodes.push({ ...row, depth: 2, actualParentId: topic });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return acc;
|
||||
},
|
||||
{ nodes: [] },
|
||||
);
|
||||
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
animation: false,
|
||||
data: graphData,
|
||||
renderer: (layer) => {
|
||||
const renderer = new CanvasRenderer();
|
||||
if (layer === 'main') {
|
||||
renderer.registerPlugin(new PluginRoughCanvasRenderer());
|
||||
}
|
||||
return renderer;
|
||||
},
|
||||
node: {
|
||||
style: (d) => {
|
||||
const { id, depth, id_num } = d;
|
||||
const color = getColor(id_num);
|
||||
|
||||
if (depth === 1) {
|
||||
return {
|
||||
fill: 'none',
|
||||
stroke: color,
|
||||
labelFontFamily: 'handwriting',
|
||||
labelFontSize: 20,
|
||||
labelText: id.replace('cat.', '').replace(/\.|_/g, ' '),
|
||||
labelTextTransform: 'capitalize',
|
||||
lineWidth: 1,
|
||||
zIndex: -1,
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
text,
|
||||
style: { size: diameter },
|
||||
} = d;
|
||||
|
||||
return {
|
||||
fill: color,
|
||||
fillOpacity: 0.7,
|
||||
stroke: color,
|
||||
fillStyle: 'cross-hatch',
|
||||
hachureGap: 1.5,
|
||||
iconFontFamily: 'handwriting',
|
||||
iconFontSize: (diameter / text.length) * 2,
|
||||
iconText: diameter > 20 ? text : '',
|
||||
iconFontWeight: 'bold',
|
||||
iconStroke: color,
|
||||
iconLineWidth: 2,
|
||||
lineWidth: (diameter || 20) ** 0.5 / 5,
|
||||
};
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'bubble-layout',
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
type: 'tooltip',
|
||||
getContent: (event, items) => {
|
||||
return `<span style="text-transform: capitalize; font-family: handwriting; font-size: 20px;">${items[0].id.replace(/\.|_/g, ' ')}</span>`;
|
||||
},
|
||||
},
|
||||
],
|
||||
behaviors: [{ type: 'drag-canvas', enable: true }, 'zoom-canvas'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
Loading…
Reference in New Issue
Block a user