Skip to content

Commit

Permalink
feat: add behavior controller and zoom-canvas (#5470)
Browse files Browse the repository at this point in the history
* feat(utils): add parseBehaviors util

* feat(constants): add events definition

* refactor(event): rename Event to BaseEvent

* refactor(utils): adjust events

* refactor(utils): move isNode to element

* feat(utils): add isEdge util

* feat(utils): add eventTargetOf util

* feat(runtime): add behavior controller

* refactor(runtime): viewport emit standard event

* feat(behaviors): add zoom-canvas

* chore(test): update test env

* refactor(runtime): export event, destroy behavior, add test cases
  • Loading branch information
Aarebecca authored Feb 26, 2024
1 parent d2d2bc6 commit b86bdcd
Show file tree
Hide file tree
Showing 52 changed files with 3,743 additions and 191 deletions.
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
"afterelementzindexchange",
"afterlayout",
"afterrender",
"afterrotate",
"aftertranslate",
"afterviewportanimate",
"afterzoom",
"bbox",
"beforeanimate",
"beforedraw",
Expand All @@ -25,7 +28,10 @@
"beforeelementzindexchange",
"beforelayout",
"beforerender",
"beforerotate",
"beforetranslate",
"beforeviewportanimate",
"beforezoom",
"cancelviewportanimate",
"dendrogram",
"elementstatechange",
Expand Down
81 changes: 81 additions & 0 deletions packages/g6/__tests__/demo/case/behavior-zoom-canvas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Graph } from '@/src';
import data from '@@/dataset/cluster.json';
import type { STDTestCase } from '../types';

export const behaviorZoomCanvas: STDTestCase = async (context) => {
const { canvas, animation } = context;
const graph = new Graph({
animation,
container: canvas,
data,
layout: {
type: 'd3force',
},
node: {
style: {
size: 20,
},
},
zoomRange: [0.5, 5],
behaviors: [{ type: 'zoom-canvas' }],
});

await graph.render();

behaviorZoomCanvas.form = [
{
label: 'Disable Zoom: ',
type: 'input',
onload: (input) => {
input.onchange = (e) => {
graph.setBehaviors((currBehaviors) => {
return currBehaviors.map((behavior, index) => {
const target = e.target as HTMLInputElement;
if (index === 0 && typeof behavior === 'object') {
return { ...behavior, enable: !target.checked };
}
return behavior;
});
});
};
},
options: { type: 'checkbox' },
},
{
type: 'button',
onload: (button) => {
button.innerText = 'Add Shortcut Zoom';
button.onclick = () => {
graph.setBehaviors((currBehaviors) => [
...currBehaviors,
{
key: 'shortcut-zoom-canvas',
type: 'zoom-canvas',
trigger: {
zoomIn: ['Control', '='],
zoomOut: ['Control', '-'],
reset: ['Control', '0'],
},
},
]);
alert('Zoom behavior added');
};
},
},

{
type: 'button',
onload: (button) => {
button.innerText = 'Remove Shortcut Zoom';
button.onclick = () => {
graph.setBehaviors((currBehaviors) => {
return currBehaviors.slice(0, 1);
});
alert('Zoom behavior removed');
};
},
},
];

return graph;
};
1 change: 1 addition & 0 deletions packages/g6/__tests__/demo/case/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './behavior-zoom-canvas';
4 changes: 3 additions & 1 deletion packages/g6/__tests__/demo/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './static';
export * as animations from './animation';
export * as cases from './case';
export * as statics from './static';
20 changes: 19 additions & 1 deletion packages/g6/__tests__/demo/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Graph } from '@/src';
import type { Canvas } from '@/src/runtime/canvas';
import type { IAnimation } from '@antv/g';

Expand Down Expand Up @@ -63,5 +64,22 @@ export interface BaseTestCase {
* @returns
*/
postprocess?: () => Promise<void>;
form?: { label?: string; type: string; options?: Record<string, unknown>; onload?: (el: HTMLElement) => void }[];
form?: PanelFormItem[];
}

export interface STDTestCase {
form?: PanelFormItem[];
(context: STDTestCaseContext): Promise<Graph>;
}

export interface STDTestCaseContext {
canvas: Canvas;
animation?: boolean;
}

type PanelFormItem = {
label?: string;
type: string;
options?: Record<string, unknown>;
onload?: (el: HTMLElement) => void;
};
22 changes: 12 additions & 10 deletions packages/g6/__tests__/main.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import '../src/preset';
import * as animations from './demo/animation';
import * as statics from './demo/static';
import * as demos from './demo';
import type { TestCase } from './demo/types';
import { createGraphCanvas } from './utils';

const CASES = {
statics,
animations,
} as unknown as { [key: string]: Record<string, TestCase> };
const CASES = demos as unknown as { [key: string]: Record<string, TestCase> };

const casesSelect = document.getElementById('demo-select') as HTMLSelectElement;
const rendererSelect = document.getElementById('renderer-select') as HTMLSelectElement;
Expand Down Expand Up @@ -71,7 +67,7 @@ function onchange(testCase: TestCase, renderer: string, animation: boolean, them

return canvas.init().then(async () => {
const result = await testCase({ canvas, animation, theme, env: 'dev' });
if (result) setTimer(result.totalDuration);
if (result?.totalDuration) setTimer(result.totalDuration);
else clearTimer();
});
}
Expand All @@ -86,7 +82,7 @@ function initialize() {
function syncParamsFromSearch() {
const searchParams = new URLSearchParams(window.location.search);
const type = searchParams.get('type') || 'statics';
const testCase = searchParams.get('case') || Object.keys(statics)[0];
const testCase = searchParams.get('case') || Object.keys(CASES.statics)[0];
const rendererName = searchParams.get('renderer') || 'canvas';
const animation = searchParams.get('animation') || 'true';

Expand All @@ -107,15 +103,21 @@ function mountCustomPanel(form: TestCase['form'] = []) {
const customPanel = document.getElementById('custom-panel')!;

form.forEach(({ label, type, options = {}, onload }) => {
const item = document.createElement('div');
item.style.display = 'flex';
item.style.alignItems = 'center';
customPanel.appendChild(item);

if (label) {
const labelEl = document.createElement('label');
labelEl.textContent = label;
customPanel.appendChild(labelEl);
item.appendChild(labelEl);
}

const element = document.createElement(type);
if (type === 'button') element.style.width = '100%';
Object.assign(element, options);
customPanel.appendChild(element);
item.appendChild(element);

onload?.(element);
});
Expand Down
Loading

0 comments on commit b86bdcd

Please sign in to comment.