jerosoler / Drawflow

Simple flow library 🖥️🖱️
https://jerosoler.github.io/Drawflow/
MIT License
4.64k stars 722 forks source link

Initial Straight Lines with Vertical Points #286

Closed SilasNiewierra closed 2 years ago

SilasNiewierra commented 2 years ago

Hi @jerosoler ,

it's me again 😄 I implemented a solution with vertical points and straight lines. Which works fine. Unfortunately when the Flowchart is imported, before I move the nodes, the Connections still start inside the node, instead of at the top and bottom.

In the attached picture you can see the following scenario:

image

Code for straight lines:

this.editor.curvature = 0
      this.editor.reroute_curvature_start_end = 0
      this.editor.reroute_curvature = 0
      this.editor.createCurvature = function (
        start_pos_x: number,
        start_pos_y: number,
        end_pos_x: number,
        end_pos_y: number
      ) {
        var center_y = (end_pos_y - start_pos_y) / 2 + start_pos_y
        return (
          ' M ' +
          start_pos_x +
          ' ' +
          start_pos_y +
          ' L ' +
          start_pos_x +
          ' ' +
          center_y +
          ' L ' +
          end_pos_x +
          ' ' +
          center_y +
          ' L ' +
          end_pos_x +
          ' ' +
          end_pos_y
        )
      }

How can I have the lines correct, as soon as the nodes/connections are imported? I don't wan't to move every node, each time I enter a flowchart?

Thanks in advance as always 😄

jerosoler commented 2 years ago

Hi @SilasNiewierra

How to import? with method import or pas json to editor?

The new createCurvature function is before start and import method?

Jero

SilasNiewierra commented 2 years ago

Good morning @jerosoler ,

the process is like this:

mounted has a setupEditor() method, once the editor is setup, the data are imported

async mounted() {
    try {
      const res = await this.api.get(`/data`)
      this.data = res.data
      this.setupEditor()
      this.importData()
    } catch (error) {
      console.log(error)
    }
  },

Setting up the editor, and making lines straight as proposed in https://github.com/jerosoler/Drawflow/issues/241

 setupEditor() {
      // Setup up the editor
      const id = document.getElementById('drawflow')
      this.editor = new Drawflow(id, this.Vue, this.internalInstance?.appContext.app._context)
      ....
      // Make lines straight
      this.editor.curvature = 0
      this.editor.reroute_curvature_start_end = 0
      this.editor.reroute_curvature = 0
      this.editor.createCurvature = function(
          start_pos_x: number,
          start_pos_y: number,
          end_pos_x: number,
          end_pos_y: number
      ) {
          var center_y = (end_pos_y - start_pos_y) / 2 + start_pos_y
          return (
              ' M ' +
              start_pos_x +
              ' ' +
              start_pos_y +
              ' L ' +
              start_pos_x +
              ' ' +
              center_y +
              ' L ' +
              end_pos_x +
              ' ' +
              center_y +
              ' L ' +
              end_pos_x +
              ' ' +
              end_pos_y
          )
      // register nodes
      ;(Object.keys(stepTemplates) as StepTypes[]).forEach((value: StepTypes) => {
              this.editor.registerNode(value, Step, nodeProps(value))
      })
      this.editor.start()
}

Import data, and prepare them to fit the drawflow structure

async importData() {
      try {
        const res = await this.api.get(`/nodes`)
        const importData = prepareDataForImport(res.data)
        this.editor.import(importData)
      } catch (error) {
        console.log(error)
      }
    },
jerosoler commented 2 years ago

I have tried with the demo and no problem:

Screenshot_20211104_082438

The components are mounted asynchronously? The height of the component is determined?

If the height can vary depending on the data, you would have to call the method: editor.updateConnectionNodes ('node-id')

For example when adding an image https://github.com/jerosoler/Drawflow/issues/43

SilasNiewierra commented 2 years ago
  1. The importData method is inside the async mounted method, so yes they are mounted asynchornously.
  2. I have different node types, with different heights. But the heights are not dynamic. They all have a fixed size predefined in the css.
SilasNiewierra commented 2 years ago

Maybe the problem is that the nodes inputs and outputs are not recognized vertically, when the data is imported?

jerosoler commented 2 years ago

The style of the nodes and the new entries is there before importing?

Maybe it's detecting the old entries?

Another option is to read the json and do an updateConnectionNodes of all nodes with the import event, to correct.

SilasNiewierra commented 2 years ago

Yes, the CSS and nodes are registered before importing the data. There are no old entries, because they is only one setup method. Before that, the chart is empty. That was my idea as well, I will try that and give you an update if it works 😄

SilasNiewierra commented 2 years ago

Hi @jerosoler ,

unfortunately this doesn't work either.

const importData = prepareDataForImport(res.data)
this.editor.import(importData)
res.data.forEach((step) => {
  this.editor.updateConnectionNodes(`node-${step.uiId}`)
})

But as soon as I manually move any node, the connection jumps to the correct position and looks good. I suspect it happens in the "nodeSelected" event. Can I manually trigger that one? So instead of updateConnectionNodes I can call something like selectNode('node-${step.uiId}')

SilasNiewierra commented 2 years ago

Or can you explain what is happening in nodeSelected? Maybe we can just call a method or set a value you set inside the nodeSelected event, which could solve this issue?

jerosoler commented 2 years ago

Have you tried it on event import?

editor.on('import', function(id) {
  res.data.forEach((step) => {
     this.editor.updateConnectionNodes(`node-${step.uiId}`)
   })
})
SilasNiewierra commented 2 years ago

When I try this:

editor.on('import', function(id) {
   console.log("info: ", id)
})

I get the following output: "info: import"? So I don't have the import data in there?

jerosoler commented 2 years ago

It does not return the imported data. But you can save it in a variable.

SilasNiewierra commented 2 years ago

I tried it with saving the data in a variable and iterating like you said in the "import" event. The method gets called for each node, but the connections are still unaffected by the change?

jerosoler commented 2 years ago

adding a settimeout? For example value: 1000ms?

SilasNiewierra commented 2 years ago

You're a genius 😄 I changed my importData method to this:

async importData() {
      try {
        const res = await this.api.get(`/nodes`)
        const importData = prepareDataForImport(res.data)
        this.editor.import(importData)
        setTimeout(() => {
          res.data.forEach((step: any) => {
            this.editor.updateConnectionNodes(`node-${step.uiId}`)
          })
        }, 500)
      } catch (error) {
        console.log(error)
      }
    },

Works like a charm. Thank you so much once again 😊