How To for Diagrams - IRobot1/three-flow-ts GitHub Wiki
const flowDiagram = new FlowDiagram()
scene.add(flowDiagram)
// add nodes, edges and connectors
// use Exporter class in examples to send to browser downloads
const exporter = new Exporter()
exporter.saveJSON(flowDiagram.save(), 'diagram')
Use Three.js FileLoader
const flowDiagram = new FlowDiagram()
scene.add(flowDiagram)
const fileLoader = new FileLoader();
fileLoader.load(`assets/diagram.json`, (data) => {
const diagram = <FlowDiagramParameters>JSON.parse(<string>data)
// load diagram into scene
flowDiagram.load(diagram)
});
The snap to grid size is an option when the diagram is create or can be changed at runtime
const flowDiagram = new FlowDiagram({ gridsize: 0.3 })
scene.add(flowDiagram)
// or change at runtime
flowDiagram.gridsize = 0
When a node or connector needs a material, a flow diagram requests a Mesh material. Override a flow diagram createMaterial method.
class CustomFlowDiagram extends FlowDiagram {
override createMeshMaterial(purpose: string, parameters: MaterialParameters): Material {
parameters.side = purpose == 'arrow' ? DoubleSide : FrontSide
return new MeshStandardMaterial(parameters);
}
}
const flowDiagram = new CustomFlowDiagram()
scene.add(flowDiagram)
// all meshes will now use MeshStandardMaterial
Another approach is override the method directly without creating a custom class. This approach is required when hosting an example in codesandbox
const flowDiagram = new FlowDiagram()
scene.add(flowDiagram)
flowDiagram.createMeshMaterial = (purpose: string, parameters: MaterialParameters): Material => {
parameters.side = purpose == 'arrow' ? DoubleSide : FrontSide
return new MeshStandardMaterial(parameters);
}
// all meshes will now use MeshStandardMaterial
When an edge is rendered using a line, a flow diagram requests a line material. To provide a custom line material, override the createLineMaterial method for your flow diagram.
class CustomFlowDiagram extends FlowDiagram {
override createLineMaterial(purpose: string, parameters: MaterialParameters): Material {
return new CustomLineMaterial(parameters);
}
}
const flowDiagram = new CustomFlowDiagram()
scene.add(flowDiagram)
// all edges will now use CustomLineMaterial
Another approach is override the method directly without creating a custom class.
const flowDiagram = new FlowDiagram()
scene.add(flowDiagram)
flowDiagram.createLineMaterial = (purpose: string, parameters: MaterialParameters): Material => {
return new CustomLineMaterial(parameters);
}
// all edges will now use CustomLineMaterial
When an edge is rendered using geometry, override the createMeshMaterial method.
Flow diagrams material requests include a purpose and color. When two meshes have the same purpose and color, the material is shared. To prevent this, override getMaterial and provide a unique purpose.
let instance = 0
let getMaterialOld = flowDiagram.getMaterial // original method
flowDiagram.getMaterial = (type: FlowMaterialType, purpose: string, parameters: MaterialParameters): Material => {
if (purpose == 'custom') purpose = `purpose${instance++}`
return getMaterialOld(type, purpose, parameters)
}
Note that its not a good practice to create hundreds of material instances for the same color. Try to use sharing when possible to improve render performance.
Use custom EventDispatcher types in your derived types to add custom event to a diagram
First review Three.js topic on FontLoader and facetype fonts. For each font, use FontLoader to create a Font object and register the name and Font with a Flow Diagram. If there is only one font, register with the name default
.
Three.js repo includes some example fonts for easy copying to get started.
const options: FlowDiagramOptions = {
options.fonts = new Map<string, Font>([])
}
const flowDiagram = new FlowDiagram(options)
scene.add(flowDiagram)
const loader = new FontLoader();
loader.load("assets/helvetiker_regular.typeface.json", (font) => {
options.fonts.set('default', font)
});
loader.load("assets/gentilis_regular.typeface.json", (font) => {
options.fonts.set('gentilis', font)
});
// use the gentilis for labels in this node
flowDiagram.addNode({ id: '4', x: -2, y: 1.5, material: {color: 'blue'}, label: { text: 'Title4', font: 'gentilis', material: {color: 'white'} } })
TODO: add plane behind diagram mesh with custom shader
TODO: add plane behind diagram mesh with custom shader