mirror of
https://gitee.com/antv/g6.git
synced 2024-11-30 10:48:24 +08:00
feat: fitView with onlyOutOfView config; fix: fitView animations; feat: offsetDistance animations;
This commit is contained in:
parent
04c3111677
commit
b853dd2355
@ -63,7 +63,7 @@
|
||||
"@antv/graphlib": "^2.0.2",
|
||||
"@antv/gui": "0.5.1-alpha.1",
|
||||
"@antv/hierarchy": "latest",
|
||||
"@antv/layout": "^1.2.11",
|
||||
"@antv/layout": "^1.2.12",
|
||||
"@antv/layout-gpu": "^1.1.5",
|
||||
"@antv/layout-wasm": "1.3.1",
|
||||
"@antv/util": "^3.3.5",
|
||||
|
@ -94,6 +94,7 @@ export default class Combo extends Node {
|
||||
});
|
||||
}
|
||||
super.draw(displayModel, diffData, diffState, animate, onfinish);
|
||||
this.changedStates = [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,7 +122,7 @@ export default class Edge extends Item {
|
||||
this.shapeMap, // shapeMap
|
||||
this.group,
|
||||
firstRendering ? 'buildIn' : 'update',
|
||||
this.changedStates,
|
||||
diffState.current.map((state) => state.name),
|
||||
this.animateFrameListener,
|
||||
(canceled) => onfinish(displayModel.id, canceled),
|
||||
);
|
||||
@ -132,6 +132,7 @@ export default class Edge extends Item {
|
||||
this.visible = true;
|
||||
this.hide(false);
|
||||
}
|
||||
this.changedStates = [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -168,14 +168,14 @@ export default abstract class Item implements IItem {
|
||||
onfinish: Function = () => {},
|
||||
) {
|
||||
// call this.renderExt.draw in extend implementations
|
||||
this.afterDrawShapeMap =
|
||||
const afterDrawShapeMap =
|
||||
this.renderExt.afterDraw?.(displayModel, {
|
||||
...this.shapeMap,
|
||||
...this.afterDrawShapeMap,
|
||||
}) || {};
|
||||
this.shapeMap = updateShapes(
|
||||
this.shapeMap,
|
||||
const shapeMap = updateShapes(
|
||||
this.afterDrawShapeMap,
|
||||
afterDrawShapeMap,
|
||||
this.group,
|
||||
false,
|
||||
(id) => {
|
||||
@ -188,7 +188,10 @@ export default abstract class Item implements IItem {
|
||||
return true;
|
||||
},
|
||||
);
|
||||
this.changedStates = [];
|
||||
this.shapeMap = {
|
||||
...this.shapeMap,
|
||||
...shapeMap,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Animation, DisplayObject, IAnimationEffectTiming } from '@antv/g';
|
||||
import Hierarchy from '@antv/hierarchy';
|
||||
import { Graph as GraphLib } from '@antv/graphlib';
|
||||
import { Graph as GraphLib, ID } from '@antv/graphlib';
|
||||
import {
|
||||
isLayoutWithIterations,
|
||||
Layout,
|
||||
@ -8,7 +7,7 @@ import {
|
||||
OutNode,
|
||||
Supervisor,
|
||||
} from '@antv/layout';
|
||||
import registery, { stdLib } from '../../stdlib';
|
||||
import registery, { Extensions, stdLib } from '../../stdlib';
|
||||
import {
|
||||
IGraph,
|
||||
isImmediatelyInvokedLayoutOptions,
|
||||
@ -38,6 +37,7 @@ export class LayoutController {
|
||||
private currentSupervisor: Supervisor | null;
|
||||
private currentAnimation: Animation | null;
|
||||
private animatedDisplayObject: DisplayObject;
|
||||
private previousNodes: Map<ID, object>;
|
||||
|
||||
constructor(graph: IGraph<any, any>) {
|
||||
this.graph = graph;
|
||||
@ -118,6 +118,15 @@ export class LayoutController {
|
||||
width,
|
||||
height,
|
||||
center,
|
||||
preset: layoutNodes.map((node) => {
|
||||
const { x, y, z } = node.data;
|
||||
if (isNaN(x) || isNaN(y)) return;
|
||||
const otherProps = this.previousNodes?.get(node.id);
|
||||
return {
|
||||
id: node.id,
|
||||
data: { x, y, z, ...otherProps },
|
||||
};
|
||||
}),
|
||||
...rest,
|
||||
});
|
||||
|
||||
@ -165,11 +174,25 @@ export class LayoutController {
|
||||
}
|
||||
|
||||
// Initialize layout.
|
||||
const useCache = layoutCtor === Extensions.DagreLayout;
|
||||
const layout = new layoutCtor({
|
||||
nodeSize,
|
||||
width,
|
||||
height,
|
||||
center,
|
||||
preset: useCache
|
||||
? layoutNodes
|
||||
.map((node) => {
|
||||
const { x, y, z } = node.data;
|
||||
if (isNaN(x) || isNaN(y)) return;
|
||||
const otherProps = this.previousNodes?.get(node.id);
|
||||
return {
|
||||
id: node.id,
|
||||
data: { x, y, z, ...otherProps },
|
||||
};
|
||||
})
|
||||
.filter(Boolean)
|
||||
: undefined,
|
||||
...rest,
|
||||
});
|
||||
this.currentLayout = layout;
|
||||
@ -314,7 +337,17 @@ export class LayoutController {
|
||||
|
||||
private updateNodesPosition(positions: LayoutMapping, animate = true) {
|
||||
const { nodes, edges } = positions;
|
||||
this.graph.updateNodePosition(nodes, undefined, !animate);
|
||||
this.previousNodes = new Map();
|
||||
const nodePositions = nodes.map((node) => {
|
||||
const { x, y, z, ...others } = node.data;
|
||||
this.previousNodes.set(node.id, others);
|
||||
const data = isNaN(z) ? { x, y } : { x, y, z };
|
||||
return {
|
||||
id: node.id,
|
||||
data,
|
||||
};
|
||||
});
|
||||
this.graph.updateNodePosition(nodePositions, undefined, !animate);
|
||||
const edgeToUpdate = edges
|
||||
.filter((edge) => edge.data.controlPoints)
|
||||
.map((edge) => ({
|
||||
|
@ -26,6 +26,8 @@ export class ViewportController {
|
||||
}: ViewportChangeHookParams) {
|
||||
const camera = this.graph.canvas.getCamera();
|
||||
const transientCamera = this.graph.transientCanvas.getCamera();
|
||||
camera.cancelLandmarkAnimation();
|
||||
transientCamera.cancelLandmarkAnimation();
|
||||
const {
|
||||
translate,
|
||||
rotate,
|
||||
@ -48,11 +50,33 @@ export class ViewportController {
|
||||
}> = {};
|
||||
|
||||
if (translate) {
|
||||
const { dx = 0, dy = 0, dz = 0 } = translate;
|
||||
const [px, py, pz] = camera.getPosition();
|
||||
const [fx, fy, fz] = camera.getFocalPoint();
|
||||
landmarkOptions.position = [px - dx, py - dy, pz - dz];
|
||||
landmarkOptions.focalPoint = [fx - dx, fy - dy, fz - dz];
|
||||
const { dx = 0, dy = 0, dz = 0, targetX, targetY, targetZ } = translate;
|
||||
const animateTargetPosition = [targetX, targetY, targetZ];
|
||||
const animateTargetFocal = [targetX, targetY, targetZ];
|
||||
if (isNaN(targetX)) {
|
||||
animateTargetPosition[0] = px - dx;
|
||||
animateTargetFocal[0] = fx - dx;
|
||||
}
|
||||
if (isNaN(targetY)) {
|
||||
animateTargetPosition[1] = py - dy;
|
||||
animateTargetFocal[1] = fy - dy;
|
||||
}
|
||||
if (isNaN(targetZ)) {
|
||||
animateTargetPosition[2] = pz - dz;
|
||||
animateTargetFocal[2] = fz - dz;
|
||||
}
|
||||
landmarkOptions.position = animateTargetPosition as [
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
];
|
||||
landmarkOptions.focalPoint = animateTargetFocal as [
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
];
|
||||
}
|
||||
|
||||
if (zoom) {
|
||||
|
@ -616,9 +616,17 @@ export class Graph<B extends BehaviorRegistry, T extends ThemeRegistry>
|
||||
}>,
|
||||
effectTiming?: CameraAnimationOptions,
|
||||
) {
|
||||
const { x: cx, y: cy } = this.getViewportCenter();
|
||||
const { dx, dy, dz } = distance;
|
||||
await this.transform(
|
||||
{
|
||||
translate: distance,
|
||||
translate: {
|
||||
dx,
|
||||
dy,
|
||||
dz,
|
||||
targetX: cx - dx,
|
||||
targetY: cy - dy,
|
||||
},
|
||||
},
|
||||
effectTiming,
|
||||
);
|
||||
@ -634,7 +642,19 @@ export class Graph<B extends BehaviorRegistry, T extends ThemeRegistry>
|
||||
effectTiming?: CameraAnimationOptions,
|
||||
) {
|
||||
const { x: cx, y: cy } = this.getViewportCenter();
|
||||
await this.translate({ dx: cx - x, dy: cy - y }, effectTiming);
|
||||
const canvasPoint = this.canvas.viewport2Canvas({ x, y });
|
||||
|
||||
await this.transform(
|
||||
{
|
||||
translate: {
|
||||
dx: cx - x,
|
||||
dy: cy - y,
|
||||
targetX: canvasPoint.x,
|
||||
targetY: canvasPoint.y,
|
||||
},
|
||||
},
|
||||
effectTiming,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -746,17 +766,20 @@ export class Graph<B extends BehaviorRegistry, T extends ThemeRegistry>
|
||||
direction = 'both',
|
||||
ratioRule = 'min',
|
||||
boundsType = 'render',
|
||||
onlyOutOfViewPort = true,
|
||||
} = rules || {};
|
||||
|
||||
const {
|
||||
min,
|
||||
max,
|
||||
center: [graphCenterX, graphCenterY],
|
||||
halfExtents,
|
||||
} =
|
||||
boundsType === 'render'
|
||||
? // Get the bounds of the whole graph content.
|
||||
this.canvas.document.documentElement.getBounds()
|
||||
: // Get the bounds of the nodes positions while the graph content is not ready.
|
||||
getLayoutBounds(this);
|
||||
} = boundsType === 'render'
|
||||
? // Get the bounds of the whole graph content.
|
||||
this.canvas.document.documentElement.getBounds()
|
||||
: // Get the bounds of the nodes positions while the graph content is not ready.
|
||||
getLayoutBounds(this);
|
||||
|
||||
const origin = this.canvas.canvas2Viewport({
|
||||
x: graphCenterX,
|
||||
y: graphCenterY,
|
||||
@ -772,6 +795,13 @@ export class Graph<B extends BehaviorRegistry, T extends ThemeRegistry>
|
||||
y: viewportHeight! - bottom,
|
||||
});
|
||||
|
||||
const isOutOfView =
|
||||
min[0] < tlInCanvas.x ||
|
||||
min[1] < tlInCanvas.y ||
|
||||
max[0] > brInCanvas.x ||
|
||||
max[1] > brInCanvas.y;
|
||||
if (onlyOutOfViewPort && !isOutOfView) return;
|
||||
|
||||
const targetViewWidth = brInCanvas.x - tlInCanvas.x;
|
||||
const targetViewHeight = brInCanvas.y - tlInCanvas.y;
|
||||
|
||||
@ -795,6 +825,8 @@ export class Graph<B extends BehaviorRegistry, T extends ThemeRegistry>
|
||||
translate: {
|
||||
dx: viewportWidth! / 2 - origin.x,
|
||||
dy: viewportHeight! / 2 - origin.y,
|
||||
targetX: graphCenterX,
|
||||
targetY: graphCenterY,
|
||||
},
|
||||
zoom: {
|
||||
ratio,
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { DEFAULT_SHAPE_STYLE, DEFAULT_TEXT_STYLE } from '../../constant';
|
||||
import { ThemeSpecification } from '../../types/theme';
|
||||
|
||||
const subjectColor = 'rgb(34,126,255)';
|
||||
const subjectColor = 'rgb(23,131,255)';
|
||||
const textColor = 'rgba(255,255,255,0.85)';
|
||||
|
||||
const nodeColor = 'rgb(34,126,255)';
|
||||
const nodeColor = 'rgb(23,131,255)';
|
||||
const edgeColor = 'rgb(153, 173, 209)';
|
||||
const comboFill = 'rgb(253, 253, 253)';
|
||||
const comboStroke = 'rgba(153,173,209,1)';
|
||||
@ -17,16 +17,16 @@ const nodeStroke = '#D0E4FF';
|
||||
export const DarkTheme = {
|
||||
node: {
|
||||
palette: [
|
||||
'#4089FF',
|
||||
'#CD75FF',
|
||||
'#06B8A8',
|
||||
'#FF8834',
|
||||
'#5888C3',
|
||||
'#FA73CD',
|
||||
'#07BCE0',
|
||||
'#CB962A',
|
||||
'#23AD61',
|
||||
'#FF8075',
|
||||
'#1783FF',
|
||||
'#00C9C9',
|
||||
'#F08F56',
|
||||
'#D580FF',
|
||||
'#7863FF',
|
||||
'#DB9D0D',
|
||||
'#60C42D',
|
||||
'#FF80CA',
|
||||
'#2491B3',
|
||||
'#17C76F',
|
||||
],
|
||||
lodStrategy: {
|
||||
levels: [
|
||||
@ -170,16 +170,16 @@ export const DarkTheme = {
|
||||
edge: {
|
||||
palette: [
|
||||
'#637088',
|
||||
'#2A59A6',
|
||||
'#854CA6',
|
||||
'#04786D',
|
||||
'#A65822',
|
||||
'#39587F',
|
||||
'#A34B85',
|
||||
'#057A92',
|
||||
'#84621B',
|
||||
'#17703F',
|
||||
'#A6534C',
|
||||
'#1783FF',
|
||||
'#00C9C9',
|
||||
'#F08F56',
|
||||
'#D580FF',
|
||||
'#7863FF',
|
||||
'#DB9D0D',
|
||||
'#60C42D',
|
||||
'#FF80CA',
|
||||
'#2491B3',
|
||||
'#17C76F',
|
||||
],
|
||||
lodStrategy: {
|
||||
levels: [
|
||||
|
@ -21,16 +21,16 @@ const disabledStroke = 'rgba(153,173,209,1)';
|
||||
export const LightTheme = {
|
||||
node: {
|
||||
palette: [
|
||||
'#4089FF',
|
||||
'#CD75FF',
|
||||
'#06B8A8',
|
||||
'#FF8834',
|
||||
'#5888C3',
|
||||
'#FA73CD',
|
||||
'#07BCE0',
|
||||
'#CB962A',
|
||||
'#23AD61',
|
||||
'#FF8075',
|
||||
'#1783FF',
|
||||
'#00C9C9',
|
||||
'#F08F56',
|
||||
'#D580FF',
|
||||
'#7863FF',
|
||||
'#DB9D0D',
|
||||
'#60C42D',
|
||||
'#FF80CA',
|
||||
'#2491B3',
|
||||
'#17C76F',
|
||||
],
|
||||
lodStrategy: {
|
||||
levels: [
|
||||
@ -172,16 +172,16 @@ export const LightTheme = {
|
||||
edge: {
|
||||
palette: [
|
||||
'#99ADD1',
|
||||
'#4089FF',
|
||||
'#CD75FF',
|
||||
'#06B8A8',
|
||||
'#FF8834',
|
||||
'#5888C3',
|
||||
'#FA73CD',
|
||||
'#07BCE0',
|
||||
'#CB962A',
|
||||
'#23AD61',
|
||||
'#FF8075',
|
||||
'#1783FF',
|
||||
'#00C9C9',
|
||||
'#F08F56',
|
||||
'#D580FF',
|
||||
'#7863FF',
|
||||
'#DB9D0D',
|
||||
'#60C42D',
|
||||
'#FF80CA',
|
||||
'#2491B3',
|
||||
'#17C76F',
|
||||
],
|
||||
lodStrategy: {
|
||||
levels: [
|
||||
|
@ -22,6 +22,9 @@ export type GraphTransformOptions = {
|
||||
dx: number;
|
||||
dy: number;
|
||||
dz: number;
|
||||
targetX: number;
|
||||
targetY: number;
|
||||
targetZ: number;
|
||||
}>;
|
||||
rotate?: {
|
||||
angle: number;
|
||||
|
@ -6,14 +6,10 @@ import {
|
||||
Path,
|
||||
Polyline,
|
||||
} from '@antv/g';
|
||||
import {
|
||||
AnimateTiming,
|
||||
IAnimate,
|
||||
IAnimates,
|
||||
IStateAnimate,
|
||||
} from '../types/animate';
|
||||
import { ItemDisplayModel, ItemShapeStyles, ShapeStyle } from '../types/item';
|
||||
import { AnimateTiming, IAnimate, IAnimates } from '../types/animate';
|
||||
import { ItemShapeStyles, ShapeStyle } from '../types/item';
|
||||
import { isArrayOverlap, replaceElements } from './array';
|
||||
import { clone, isString, uniq } from '@antv/util';
|
||||
|
||||
/**
|
||||
* Initial(timing = show) shape animation start from init shape styles, and end to the shape's style config.
|
||||
@ -28,9 +24,8 @@ export const getShapeAnimateBeginStyles = (shape) => {
|
||||
offsetDistance: 0,
|
||||
};
|
||||
if (['line', 'polyline', 'path'].includes(shapeType)) {
|
||||
const totalLength = shape.getTotalLength();
|
||||
return {
|
||||
lineDash: [0, totalLength],
|
||||
lineDash: [0, '100%'],
|
||||
...commonStyles,
|
||||
};
|
||||
} else if (shapeType === 'circle') {
|
||||
@ -136,13 +131,11 @@ const groupTimingAnimates = (
|
||||
const isStateUpdate = segmentedTiming === 'stateUpdate';
|
||||
animates[isStateUpdate ? 'update' : segmentedTiming].forEach((item: any) => {
|
||||
const { order = 0, states } = item;
|
||||
if (
|
||||
!isStateUpdate ||
|
||||
(isStateUpdate && isArrayOverlap(states, changedStates))
|
||||
) {
|
||||
timingAnimateGroups[order] = timingAnimateGroups[order] || [];
|
||||
timingAnimateGroups[order].push(item);
|
||||
if (states?.length) {
|
||||
if (!isArrayOverlap(states, changedStates)) return;
|
||||
}
|
||||
timingAnimateGroups[order] = timingAnimateGroups[order] || [];
|
||||
timingAnimateGroups[order].push(item);
|
||||
});
|
||||
return timingAnimateGroups;
|
||||
};
|
||||
@ -255,7 +248,13 @@ const runAnimateGroupOnShapes = (
|
||||
}
|
||||
return animation;
|
||||
});
|
||||
if (maxDurationIdx > -1) animations[maxDurationIdx].onfinish = onfinish;
|
||||
if (maxDurationIdx > -1) {
|
||||
const selfOnfinish = animations[maxDurationIdx].onfinish;
|
||||
animations[maxDurationIdx].onfinish = () => {
|
||||
selfOnfinish?.();
|
||||
onfinish?.();
|
||||
};
|
||||
}
|
||||
return animations;
|
||||
};
|
||||
|
||||
@ -276,19 +275,51 @@ const runAnimateOnShape = (
|
||||
animateConfig,
|
||||
) => {
|
||||
let animateArr;
|
||||
let percentLineDash = false;
|
||||
if (!fields?.length) {
|
||||
animateArr = getStyleDiff(shape.attributes, targetStyle);
|
||||
} else {
|
||||
animateArr = [{}, {}];
|
||||
fields.forEach((key) => {
|
||||
animateArr[0][key] = shape.attributes.hasOwnProperty(key)
|
||||
? shape.style[key]
|
||||
: beginStyle[key];
|
||||
animateArr[1][key] =
|
||||
targetStyle[key] === undefined ? animateArr[0][key] : targetStyle[key];
|
||||
if (key === 'lineDash' && animateArr[1][key].includes('100%')) {
|
||||
const totalLength = (shape as Line | Polyline | Path).getTotalLength();
|
||||
replaceElements(animateArr[1][key], '100%', totalLength);
|
||||
animateArr[0][key] =
|
||||
shape.style[key] === undefined
|
||||
? clone(beginStyle[key])
|
||||
: clone(shape.style[key]);
|
||||
if (targetStyle[key] === undefined) return;
|
||||
animateArr[1][key] = clone(targetStyle[key]);
|
||||
if (key === 'lineDash') {
|
||||
const beginPercents = uniq(
|
||||
animateArr[0][key].filter(
|
||||
(val) => isString(val) && val.includes('%'),
|
||||
),
|
||||
);
|
||||
const targetPercents = uniq(
|
||||
animateArr[1][key].filter(
|
||||
(val) => isString(val) && val.includes('%'),
|
||||
),
|
||||
);
|
||||
if (beginPercents.length || targetPercents.length) {
|
||||
percentLineDash = clone(animateArr[0].lineDash);
|
||||
const totalLength = (
|
||||
shape as Line | Polyline | Path
|
||||
).getTotalLength();
|
||||
beginPercents.forEach((percent, i) => {
|
||||
replaceElements(
|
||||
animateArr[0][key],
|
||||
percent,
|
||||
(Number(percent.replace('%', '')) / 100) * totalLength,
|
||||
);
|
||||
});
|
||||
targetPercents.forEach((percent, i) => {
|
||||
replaceElements(
|
||||
animateArr[1][key],
|
||||
percent,
|
||||
(Number(percent.replace('%', '')) / 100) * totalLength,
|
||||
);
|
||||
});
|
||||
}
|
||||
} else if (key === 'offsetDistance') {
|
||||
animateArr[1][key] = animateArr[1][key] || 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -300,7 +331,13 @@ const runAnimateOnShape = (
|
||||
);
|
||||
return;
|
||||
}
|
||||
return shape.animate(animateArr, animateConfig);
|
||||
const animation = shape.animate(animateArr, animateConfig);
|
||||
if (percentLineDash) {
|
||||
animation.onfinish = () => {
|
||||
shape.style.lineDash = percentLineDash;
|
||||
};
|
||||
}
|
||||
return animation;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,190 +0,0 @@
|
||||
import { Graph as BaseGraph, extend, Extensions } from '../../../src/index';
|
||||
import { container, height, width } from '../../datasets/const';
|
||||
|
||||
const Graph = extend(BaseGraph, {
|
||||
behaviors: {
|
||||
'hover-activate': Extensions.HoverActivate,
|
||||
'brush-select': Extensions.BrushSelect,
|
||||
},
|
||||
plugins: {
|
||||
legend: Extensions.Legend,
|
||||
},
|
||||
});
|
||||
export default () => {
|
||||
const data = {
|
||||
nodes: [
|
||||
{
|
||||
id: 1,
|
||||
data: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
type: 'circle-node',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
data: {
|
||||
x: 200,
|
||||
y: 100,
|
||||
type: 'rect-node',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
data: {
|
||||
x: 100,
|
||||
y: 200,
|
||||
type: 'rect-node',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
data: {
|
||||
x: 200,
|
||||
y: 200,
|
||||
type: 'rect-node',
|
||||
},
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
source: 1,
|
||||
target: 2,
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const graph = new Graph({
|
||||
container,
|
||||
width,
|
||||
height,
|
||||
data: {
|
||||
nodes: [
|
||||
{ id: 'node1', data: { x: 100, y: 200, nodeType: 'a' } },
|
||||
{ id: 'node2', data: { x: 200, y: 250, nodeType: 'b' } },
|
||||
{ id: 'node3', data: { x: 200, y: 350, nodeType: 'b' } },
|
||||
{ id: 'node4', data: { x: 300, y: 250, nodeType: 'c' } },
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
id: 'edge1',
|
||||
source: 'node1',
|
||||
target: 'node2',
|
||||
data: { edgeType: 'e1' },
|
||||
},
|
||||
{
|
||||
id: 'edge2',
|
||||
source: 'node2',
|
||||
target: 'node3',
|
||||
data: { edgeType: 'e2' },
|
||||
},
|
||||
{
|
||||
id: 'edge3',
|
||||
source: 'node3',
|
||||
target: 'node4',
|
||||
data: { edgeType: 'e3' },
|
||||
},
|
||||
{
|
||||
id: 'edge4',
|
||||
source: 'node1',
|
||||
target: 'node4',
|
||||
data: { edgeType: 'e3' },
|
||||
},
|
||||
],
|
||||
},
|
||||
modes: {
|
||||
default: [
|
||||
'click-select',
|
||||
'hover-activate',
|
||||
'drag-canvas',
|
||||
'zoom-canvas',
|
||||
'drag-node',
|
||||
],
|
||||
},
|
||||
autoFit: 'view',
|
||||
plugins: [
|
||||
{
|
||||
type: 'legend',
|
||||
key: 'legend1',
|
||||
size: 'fit-content',
|
||||
renderer: 'canvas',
|
||||
background: '#ccc',
|
||||
orientation: 'horizontal',
|
||||
node: {
|
||||
enable: true,
|
||||
padding: [20, 20],
|
||||
title: 'node-legend',
|
||||
typeField: 'nodeType',
|
||||
rows: 1,
|
||||
cols: 4,
|
||||
labelStyle: {
|
||||
spacing: 8,
|
||||
fontSize: 20,
|
||||
},
|
||||
markerStyle: {
|
||||
shape: 'circle',
|
||||
size: (type) => {
|
||||
return type === 'a' ? 10 : 20;
|
||||
},
|
||||
color: (type) => {
|
||||
return type === 'a' ? '#f00' : '#00f';
|
||||
},
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
enable: true,
|
||||
padding: [10, 20],
|
||||
title: 'edge-legend',
|
||||
typeField: 'edgeType',
|
||||
markerStyle: {
|
||||
color: (type) => {
|
||||
switch (type) {
|
||||
case 'e1':
|
||||
return '#00f';
|
||||
case 'e2':
|
||||
return '#f0f';
|
||||
case 'e3':
|
||||
return '#0ff';
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
// theme: {
|
||||
// type: 'spec',
|
||||
// base: 'light',
|
||||
// specification: {
|
||||
// node: {
|
||||
// dataTypeField: 'type',
|
||||
// palette: { 'circle-node': '#f00', 'rect-node': '#0f0' },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
});
|
||||
|
||||
graph.on('canvas:click', (e) => {
|
||||
graph.addData('node', {
|
||||
id: 'ewnnode',
|
||||
data: {
|
||||
x: 100,
|
||||
y: 300,
|
||||
nodeType: 'd',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// // 在平移过的基础上再 fitView 带动画,位置不对
|
||||
// let transformed = true;
|
||||
// graph.on('canvas:click', (e) => {
|
||||
// graph.fitView({}, transformed ? { duration: 500 } : undefined);
|
||||
// // transformed = !transformed;
|
||||
// });
|
||||
// graph.on('canvas:contextmenu', (e) => {
|
||||
// e.preventDefault();
|
||||
// graph.translate({ dx: 100, dy: 100 });
|
||||
// });
|
||||
|
||||
return graph;
|
||||
};
|
@ -73,13 +73,11 @@ import triangle from './demo/triangle';
|
||||
import user_defined_canvas from './user-defined-canvas/circular';
|
||||
import visual from './visual/visual';
|
||||
import watermarker from './plugins/watermarker';
|
||||
import bugplayground from './demo/bugplayground';
|
||||
|
||||
export { default as timebar_time } from './plugins/timebar-time';
|
||||
export { default as timebar_chart } from './plugins/timebar-chart';
|
||||
|
||||
export {
|
||||
bugplayground,
|
||||
anchor,
|
||||
animations_node_build_in,
|
||||
arrow,
|
||||
|
@ -1,28 +1,58 @@
|
||||
import G6 from '@antv/g6';
|
||||
import { Graph as BaseGraph, extend, Extensions } from '@antv/g6';
|
||||
|
||||
const { CubicEdge } = Extensions;
|
||||
class CustomEdge extends CubicEdge {
|
||||
afterDraw(model, shapeMap, shapesChanged) {
|
||||
const { keyShape } = shapeMap;
|
||||
console.log('model.data', model.data);
|
||||
const { visible, ...otherStyles } = model.data?.otherShapes?.buShape || {};
|
||||
if (visible) {
|
||||
return {
|
||||
buShape: this.upsertShape(
|
||||
'circle',
|
||||
'buShape',
|
||||
{
|
||||
r: 4,
|
||||
x: 0,
|
||||
y: 0,
|
||||
fill: '#1890ff',
|
||||
offsetPath: keyShape,
|
||||
zIndex: 1,
|
||||
...otherStyles, // merged style from mappers and states
|
||||
},
|
||||
shapeMap,
|
||||
model,
|
||||
),
|
||||
};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Graph = extend(BaseGraph, {
|
||||
edges: {
|
||||
'custom-edge': CustomEdge,
|
||||
},
|
||||
});
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{
|
||||
id: 'a',
|
||||
data: {
|
||||
x: 200,
|
||||
y: 100,
|
||||
cluster: '1',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'b',
|
||||
data: {
|
||||
x: 100,
|
||||
y: 200,
|
||||
cluster: '2',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'c',
|
||||
data: {
|
||||
x: 300,
|
||||
y: 200,
|
||||
cluster: '3',
|
||||
},
|
||||
},
|
||||
@ -44,13 +74,14 @@ const data = {
|
||||
const container = document.getElementById('container');
|
||||
const width = container.scrollWidth;
|
||||
const height = container.scrollHeight || 500;
|
||||
let graph = new G6.Graph({
|
||||
let graph = new Graph({
|
||||
container: 'container',
|
||||
width,
|
||||
height,
|
||||
modes: { default: [] },
|
||||
layout: {
|
||||
type: 'grid',
|
||||
rows: 2,
|
||||
},
|
||||
theme: {
|
||||
type: 'spec',
|
||||
@ -104,9 +135,7 @@ let graph = new G6.Graph({
|
||||
};
|
||||
},
|
||||
edge: {
|
||||
keyShape: {
|
||||
lineDash: [0, '100%'],
|
||||
},
|
||||
type: 'custom-edge',
|
||||
animates: {
|
||||
update: [
|
||||
{
|
||||
@ -116,6 +145,13 @@ let graph = new G6.Graph({
|
||||
iterations: Infinity,
|
||||
duration: 2000,
|
||||
},
|
||||
{
|
||||
fields: ['offsetDistance'],
|
||||
shapeId: 'buShape',
|
||||
states: ['circleRunning'],
|
||||
iterations: Infinity,
|
||||
duration: 2000,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
@ -143,7 +179,7 @@ let graph = new G6.Graph({
|
||||
growing: {
|
||||
keyShape: {
|
||||
lineWidth: 2,
|
||||
lineDash: ['100%', 10000],
|
||||
lineDash: ['100%', 0],
|
||||
},
|
||||
},
|
||||
running: {
|
||||
@ -153,6 +189,14 @@ let graph = new G6.Graph({
|
||||
// TODO: lineDashOffset
|
||||
},
|
||||
},
|
||||
circleRunning: {
|
||||
otherShapes: {
|
||||
buShape: {
|
||||
visible: true,
|
||||
offsetDistance: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
data,
|
||||
});
|
||||
@ -186,6 +230,7 @@ const actions = {
|
||||
if (graph.getItemState(edge.id, 'growing')) {
|
||||
graph.setItemState(edge.id, 'growing', false);
|
||||
} else {
|
||||
graph.setItemState(edge.id, 'circleRunning', false);
|
||||
graph.setItemState(edge.id, 'running', false);
|
||||
graph.setItemState(edge.id, 'growing', true);
|
||||
}
|
||||
@ -196,11 +241,23 @@ const actions = {
|
||||
if (graph.getItemState(edge.id, 'running')) {
|
||||
graph.setItemState(edge.id, 'running', false);
|
||||
} else {
|
||||
graph.setItemState(edge.id, 'circleRunning', false);
|
||||
graph.setItemState(edge.id, 'growing', false);
|
||||
graph.setItemState(edge.id, 'running', true);
|
||||
}
|
||||
});
|
||||
},
|
||||
CircleRunning: () => {
|
||||
graph.getAllEdgesData().forEach((edge) => {
|
||||
if (graph.getItemState(edge.id, 'circleRunning')) {
|
||||
graph.setItemState(edge.id, 'circleRunning', false);
|
||||
} else {
|
||||
graph.setItemState(edge.id, 'running', false);
|
||||
graph.setItemState(edge.id, 'growing', false);
|
||||
graph.setItemState(edge.id, 'circleRunning', true);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -78,8 +78,8 @@ importers:
|
||||
specifier: latest
|
||||
version: 0.6.11
|
||||
'@antv/layout':
|
||||
specifier: ^1.2.11
|
||||
version: 1.2.11(workerize-loader@2.0.2)
|
||||
specifier: ^1.2.12
|
||||
version: 1.2.12(workerize-loader@2.0.2)
|
||||
'@antv/layout-gpu':
|
||||
specifier: ^1.1.5
|
||||
version: 1.1.5(workerize-loader@2.0.2)
|
||||
@ -1302,7 +1302,7 @@ packages:
|
||||
'@antv/graphlib': 2.0.2
|
||||
'@antv/gui': 0.5.1-alpha.1(@antv/g@5.18.16)
|
||||
'@antv/hierarchy': 0.6.11
|
||||
'@antv/layout': 1.2.11(workerize-loader@2.0.2)
|
||||
'@antv/layout': 1.2.12(workerize-loader@2.0.2)
|
||||
'@antv/layout-gpu': 1.1.5(workerize-loader@2.0.2)
|
||||
'@antv/layout-wasm': 1.3.1
|
||||
'@antv/util': 3.3.5
|
||||
@ -1577,8 +1577,8 @@ packages:
|
||||
tslib: 2.6.2
|
||||
dev: false
|
||||
|
||||
/@antv/layout@1.2.11(workerize-loader@2.0.2):
|
||||
resolution: {integrity: sha512-UJ1J/PwP0muP1k6T8PRaYp0nwbpD0w7iIOdYesQ7KOVUIfYqbwkNBOOmxw4LX5gHR2ZQ9fnyDu2PH+aNUjzmhg==}
|
||||
/@antv/layout@1.2.12(workerize-loader@2.0.2):
|
||||
resolution: {integrity: sha512-/FKb7xXDx5iss013BB2Y7wB2TDokDxnzvBe0HhjNkvsiLFO71z+edvzipq/6QXtgJIwRQChaChiYCZhPewZPaQ==}
|
||||
dependencies:
|
||||
'@antv/event-emitter': 0.1.3
|
||||
'@antv/graphlib': 2.0.2
|
||||
@ -1589,7 +1589,7 @@ packages:
|
||||
d3-octree: 1.0.2
|
||||
d3-quadtree: 3.0.1
|
||||
ml-matrix: 6.10.5
|
||||
tslib: 2.5.0
|
||||
tslib: 2.6.2
|
||||
transitivePeerDependencies:
|
||||
- workerize-loader
|
||||
dev: false
|
||||
@ -13391,11 +13391,11 @@ packages:
|
||||
eslint-plugin-eslint-comments: 3.2.0(eslint@6.8.0)
|
||||
eslint-plugin-import: 2.28.1(@typescript-eslint/parser@2.34.0)(eslint@6.8.0)
|
||||
eslint-plugin-jest: 22.21.0(eslint@6.8.0)
|
||||
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.48.0)
|
||||
eslint-plugin-jsx-a11y: 6.7.1(eslint@6.8.0)
|
||||
eslint-plugin-markdown: 1.0.2
|
||||
eslint-plugin-prettier: 3.4.1(eslint-config-prettier@4.3.0)(eslint@6.8.0)(prettier@2.8.8)
|
||||
eslint-plugin-promise: 4.3.1
|
||||
eslint-plugin-react: 7.13.0(eslint@8.48.0)
|
||||
eslint-plugin-react: 7.13.0(eslint@6.8.0)
|
||||
eslint-plugin-react-hooks: 1.7.0(eslint@6.8.0)
|
||||
eslint-plugin-unicorn: 8.0.2(eslint@6.8.0)
|
||||
stylelint: 10.1.0
|
||||
@ -20448,8 +20448,8 @@ packages:
|
||||
eslint: 6.8.0
|
||||
eslint-config-airbnb-base: 13.2.0(eslint-plugin-import@2.28.1)(eslint@6.8.0)
|
||||
eslint-plugin-import: 2.28.1(@typescript-eslint/parser@2.34.0)(eslint@6.8.0)
|
||||
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.48.0)
|
||||
eslint-plugin-react: 7.13.0(eslint@8.48.0)
|
||||
eslint-plugin-jsx-a11y: 6.7.1(eslint@6.8.0)
|
||||
eslint-plugin-react: 7.13.0(eslint@6.8.0)
|
||||
object.assign: 4.1.4
|
||||
object.entries: 1.1.7
|
||||
dev: true
|
||||
@ -20466,8 +20466,8 @@ packages:
|
||||
eslint: 5.16.0
|
||||
eslint-config-airbnb-base: 13.2.0(eslint-plugin-import@2.28.1)(eslint@5.16.0)
|
||||
eslint-plugin-import: 2.28.1(@typescript-eslint/parser@1.10.2)(eslint@5.16.0)
|
||||
eslint-plugin-jsx-a11y: 6.7.1(eslint@5.16.0)
|
||||
eslint-plugin-react: 7.33.2(eslint@5.16.0)
|
||||
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.48.0)
|
||||
eslint-plugin-react: 7.33.2(eslint@8.48.0)
|
||||
object.assign: 4.1.4
|
||||
object.entries: 1.1.7
|
||||
dev: true
|
||||
@ -21279,7 +21279,7 @@ packages:
|
||||
resolve: 1.22.6
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-react@7.13.0(eslint@8.48.0):
|
||||
/eslint-plugin-react@7.13.0(eslint@6.8.0):
|
||||
resolution: {integrity: sha512-uA5LrHylu8lW/eAH3bEQe9YdzpPaFd9yAJTwTi/i/BKTD7j6aQMKVAdGM/ML72zD6womuSK7EiGtMKuK06lWjQ==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
@ -21287,7 +21287,7 @@ packages:
|
||||
dependencies:
|
||||
array-includes: 3.1.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.48.0
|
||||
eslint: 6.8.0
|
||||
has: 1.0.4
|
||||
jsx-ast-utils: 2.4.1
|
||||
object.fromentries: 2.0.7
|
||||
@ -21411,7 +21411,6 @@ packages:
|
||||
resolve: 2.0.0-next.4
|
||||
semver: 6.3.1
|
||||
string.prototype.matchall: 4.0.10
|
||||
dev: false
|
||||
|
||||
/eslint-plugin-unicorn@20.1.0(eslint@7.32.0):
|
||||
resolution: {integrity: sha512-XQxLBJT/gnwyRR6cfYsIK1AdekQchAt5tmcsnldevGjgR2xoZsRUa5/i6e0seNHy2RoT57CkTnbVHwHF8No8LA==}
|
||||
@ -22424,10 +22423,10 @@ packages:
|
||||
eslint-plugin-eslint-comments: 3.2.0(eslint@5.16.0)
|
||||
eslint-plugin-import: 2.28.1(@typescript-eslint/parser@1.10.2)(eslint@5.16.0)
|
||||
eslint-plugin-jest: 22.21.0(eslint@5.16.0)
|
||||
eslint-plugin-jsx-a11y: 6.7.1(eslint@5.16.0)
|
||||
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.48.0)
|
||||
eslint-plugin-markdown: 1.0.2
|
||||
eslint-plugin-promise: 4.3.1
|
||||
eslint-plugin-react: 7.33.2(eslint@5.16.0)
|
||||
eslint-plugin-react: 7.33.2(eslint@8.48.0)
|
||||
eslint-plugin-unicorn: 8.0.2(eslint@5.16.0)
|
||||
father-build: 1.17.1
|
||||
fs-extra: 8.1.0
|
||||
|
Loading…
Reference in New Issue
Block a user