Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add 3d elements, plugin (#5597)
* refactor: adjust exports, use enum replace const enum * fix: fix issue that unexpected z attr * feat(utils): add TupleMap and getCacheKey * feat(elements): add 3d elements * feat(plugins): add 3d light * refactor: adjust 3d renderer * refactor: adjust exports * test: add demos * chore: config packages.json, jest config * test: fix test case * chore: update g6-extension-3d version * chore: setup project configs * test: fix demo type issue * chore: config tsconfig for type-check
- Loading branch information
Showing
52 changed files
with
1,091 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,7 @@ | |
"GSHAPE", | ||
"mindmap", | ||
"onframe", | ||
"Phong", | ||
"Polyline", | ||
"ranksep" | ||
], | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export * from './layer-top'; | ||
export * from './position'; | ||
export * from './shapes'; | ||
export * from './solar-system'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import type { G6Spec, GraphData } from '@antv/g6'; | ||
import { Graph, register } from '@antv/g6'; | ||
import { Light, Line3D, Plane, Sphere, renderer } from '../../src'; | ||
|
||
export const layerTop = async (context: G6Spec) => { | ||
register('plugin', '3d-light', Light); | ||
register('node', 'sphere', Sphere); | ||
register('node', 'plane', Plane); | ||
register('edge', 'line3d', Line3D); | ||
|
||
const result = await fetch('https://assets.antv.antgroup.com/g6/3-layer-top.json'); | ||
const { nodes, edges } = await result.json(); | ||
|
||
const colors = ['rgb(240, 134, 82)', 'rgb(30, 160, 230)', 'rgb(122, 225, 116)']; | ||
const data: GraphData = {}; | ||
data.nodes = nodes.map(({ name, pos, layer }: any) => ({ | ||
id: name, | ||
data: { layer }, | ||
style: { | ||
type: 'sphere', | ||
radius: 10, | ||
color: colors[layer - 1], | ||
materialType: 'phong', | ||
...pos, | ||
}, | ||
})); | ||
|
||
new Array(3).fill(0).forEach((_, i) => { | ||
data.nodes!.push({ | ||
id: `plane-${i + 1}`, | ||
style: { | ||
type: 'plane', | ||
size: 1000, | ||
color: colors[i], | ||
y: -300 + 300 * i + 10, | ||
}, | ||
}); | ||
}); | ||
|
||
data.edges = edges.map(({ source, target }: any) => ({ | ||
source, | ||
target, | ||
})); | ||
|
||
const graph = new Graph({ | ||
...context, | ||
renderer, | ||
data, | ||
node: { | ||
style: {}, | ||
}, | ||
edge: { | ||
style: { | ||
type: 'line3d', | ||
lineWidth: 5, | ||
}, | ||
}, | ||
plugins: [ | ||
{ | ||
type: '3d-light', | ||
directional: { | ||
direction: [0, 0, 1], | ||
}, | ||
}, | ||
], | ||
}); | ||
|
||
await graph.render(); | ||
|
||
return graph; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import type { G6Spec } from '@antv/g6'; | ||
import { Graph, register } from '@antv/g6'; | ||
import { Light, Line3D, Sphere, renderer } from '../../src'; | ||
|
||
export const positionValidate = async (context: G6Spec) => { | ||
register('plugin', '3d-light', Light); | ||
register('node', 'sphere', Sphere); | ||
register('edge', 'line3d', Line3D); | ||
|
||
const graph = new Graph({ | ||
...context, | ||
renderer, | ||
data: { | ||
nodes: [ | ||
{ id: '1', style: { x: 100, y: 100 } }, | ||
{ id: '2', style: { x: 200, y: 200 } }, | ||
{ id: '3', style: { x: 200, y: 100, z: 150 } }, | ||
], | ||
edges: [ | ||
{ source: '1', target: '2' }, | ||
{ source: '2', target: '3' }, | ||
{ source: '1', target: '3' }, | ||
], | ||
}, | ||
node: { | ||
style: { type: 'sphere', materialType: 'phong' }, | ||
}, | ||
edge: { | ||
style: { | ||
type: 'line3d', | ||
}, | ||
}, | ||
plugins: [ | ||
{ | ||
type: '3d-light', | ||
directional: { | ||
direction: [0, 0, 1], | ||
}, | ||
}, | ||
], | ||
}); | ||
|
||
await graph.render(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import type { G6Spec } from '@antv/g6'; | ||
import { Graph, register } from '@antv/g6'; | ||
import { Capsule, Cone, Cube, Cylinder, Light, Plane, Sphere, Torus, renderer } from '../../src'; | ||
|
||
export const shapes = async (context: G6Spec) => { | ||
register('plugin', '3d-light', Light); | ||
register('node', 'sphere', Sphere); | ||
register('node', 'plane', Plane); | ||
register('node', 'cylinder', Cylinder); | ||
register('node', 'cone', Cone); | ||
register('node', 'cube', Cube); | ||
register('node', 'capsule', Capsule); | ||
register('node', 'torus', Torus); | ||
|
||
const graph = new Graph({ | ||
...context, | ||
renderer, | ||
data: { | ||
nodes: [ | ||
{ | ||
id: '1', | ||
style: { | ||
type: 'sphere', | ||
texture: 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*cdTdTI2bNl8AAAAAAAAAAAAADmJ7AQ/original', | ||
}, | ||
}, | ||
{ id: '2', style: { type: 'plane', size: 50 } }, | ||
{ id: '3', style: { type: 'cylinder' } }, | ||
{ id: '4', style: { type: 'cone' } }, | ||
{ | ||
id: '5', | ||
style: { | ||
type: 'cube', | ||
texture: 'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*8TlCRIsKeUkAAAAAAAAAAAAAARQnAQ', | ||
}, | ||
}, | ||
{ id: '6', style: { type: 'capsule' } }, | ||
{ id: '7', style: { type: 'torus' } }, | ||
], | ||
}, | ||
node: { | ||
style: { | ||
materialType: 'phong', | ||
x: (_, i) => 100 + (i % 5) * 100, | ||
y: (_, i) => 100 + Math.floor(i / 5) * 100, | ||
}, | ||
}, | ||
plugins: [ | ||
{ | ||
type: '3d-light', | ||
directional: { | ||
direction: [0, 0, 1], | ||
}, | ||
}, | ||
], | ||
}); | ||
|
||
await graph.render(); | ||
}; |
112 changes: 112 additions & 0 deletions
112
packages/g6-extension-3d/__tests__/demos/solar-system.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import type { DisplayObject } from '@antv/g'; | ||
import type { G6Spec, Vector3 } from '@antv/g6'; | ||
import { Graph, register } from '@antv/g6'; | ||
import { Light, Sphere, renderer } from '../../src'; | ||
|
||
export const solarSystem = async (context: G6Spec) => { | ||
register('plugin', '3d-light', Light); | ||
register('node', 'sphere', Sphere); | ||
|
||
const graph = new Graph({ | ||
...context, | ||
renderer, | ||
background: 'black', | ||
data: { | ||
nodes: [ | ||
{ | ||
id: 'sum', | ||
style: { | ||
x: 300, | ||
y: 300, | ||
radius: 100, | ||
texture: 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-mZfQr8LtPUAAAAAAAAAAAAADmJ7AQ/original', | ||
}, | ||
}, | ||
{ | ||
id: 'mars', | ||
style: { | ||
x: 430, | ||
y: 300, | ||
z: 0, | ||
radius: 20, | ||
texture: 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*mniGTZktpecAAAAAAAAAAAAADmJ7AQ/original', | ||
}, | ||
}, | ||
{ | ||
id: 'earth', | ||
style: { | ||
x: 500, | ||
y: 300, | ||
z: 0, | ||
radius: 30, | ||
texture: 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*cdTdTI2bNl8AAAAAAAAAAAAADmJ7AQ/original', | ||
}, | ||
}, | ||
{ | ||
id: 'jupiter', | ||
style: { | ||
x: 600, | ||
y: 300, | ||
z: 0, | ||
radius: 50, | ||
texture: 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*t_mQSZYAT70AAAAAAAAAAAAADmJ7AQ/original', | ||
}, | ||
}, | ||
], | ||
}, | ||
node: { | ||
style: { | ||
type: 'sphere', | ||
materialShininess: 0, | ||
labelText: (d) => d.id, | ||
}, | ||
}, | ||
plugins: [ | ||
{ | ||
type: '3d-light', | ||
directional: { | ||
direction: [0, 0, 1], | ||
}, | ||
}, | ||
], | ||
}); | ||
|
||
await graph.render(); | ||
|
||
// @ts-expect-error graph is private | ||
const element = graph.context.element!; | ||
|
||
const sum = element.getElement('sum')!; | ||
const mars = element.getElement('mars')!; | ||
const earth = element.getElement('earth')!; | ||
const jupiter = element.getElement('jupiter')!; | ||
|
||
const setRotation = (element: DisplayObject, speed: number) => { | ||
setInterval(() => { | ||
element.rotate(0, -speed, 0); | ||
}, 30); | ||
}; | ||
setRotation(sum, 0.1); | ||
setRotation(mars, 0.8); | ||
setRotation(earth, 1); | ||
setRotation(jupiter, 0.5); | ||
|
||
const setRevolution = (element: DisplayObject, center: Vector3, speed: number) => { | ||
setInterval(() => { | ||
const [x, y, z] = element.getPosition(); | ||
const [cx, cy, cz] = center; | ||
const angle = (speed * Math.PI) / 180; | ||
|
||
const newX = (x - cx) * Math.cos(angle) + (z - cz) * Math.sin(angle) + cx; | ||
const newZ = -(x - cx) * Math.sin(angle) + (z - cz) * Math.cos(angle) + cz; | ||
|
||
element.setPosition(newX, y, newZ); | ||
}, 30); | ||
}; | ||
|
||
setRevolution(mars, [300, 300, 0], 1.5); | ||
setRevolution(earth, [300, 300, 0], 1); | ||
setRevolution(jupiter, [300, 300, 0], 0.5); | ||
|
||
return graph; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>@antv/g6-extension-3d</title> | ||
<style> | ||
#container { | ||
width: 500px; | ||
height: 500px; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div id="container"></div> | ||
<script type="module" src="./main.ts"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import GUI from 'lil-gui'; | ||
import * as demos from './demos'; | ||
|
||
const demoNames = Object.keys(demos); | ||
|
||
const options = { | ||
demo: '', | ||
}; | ||
|
||
const panel = new GUI({ autoPlace: true }); | ||
const __STORAGE__ = '__G6_EXTENSION_3D_DEMO__'; | ||
const load = () => { | ||
const data = localStorage.getItem(__STORAGE__); | ||
if (data) panel.load(JSON.parse(data)); | ||
}; | ||
const save = () => { | ||
localStorage.setItem(__STORAGE__, JSON.stringify(panel.save())); | ||
}; | ||
panel | ||
.add(options, 'demo', demoNames) | ||
.name('Demo') | ||
.onChange((name: string) => { | ||
render(name); | ||
save(); | ||
}); | ||
load(); | ||
|
||
function initContainer() { | ||
const container = document.getElementById('container')!; | ||
container.innerHTML = ''; | ||
return container; | ||
} | ||
|
||
function initContext() { | ||
const container = initContainer(); | ||
return { container }; | ||
} | ||
|
||
function render(name: string) { | ||
const context = initContext(); | ||
const demo = demos[name as keyof typeof demos]; | ||
demo(context); | ||
} |
Oops, something went wrong.