How To for Diagrams - IRobot1/three-flow-ts GitHub Wiki

Save a Diagram to a File

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')

Load a Diagram from a Server

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)
});

Change the Diagram Snap to Grid Size

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

Customize the Materials used by Nodes or Connectors

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

Customize the Materials used by Edges

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.

Share Materials

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.

Add Custom Events to a Diagram

Use custom EventDispatcher types in your derived types to add custom event to a diagram

Register a Font for Use by Three-Flow 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'} } })

Show Snap To Grid Lines

TODO: add plane behind diagram mesh with custom shader

Show Snap To Grid Dots

TODO: add plane behind diagram mesh with custom shader

⚠️ **GitHub.com Fallback** ⚠️