jerosoler / Drawflow

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

Programmatically Create Reroute Point #46

Closed mcantonbul closed 2 years ago

mcantonbul commented 3 years ago

I want to programmatically add points between nodes. I think it would be great if such a feature could be added to the library.

Like: createReroutePoint(pos_x, pos_y, output_node_id, input_node_id, output_class?, input_class?)

createReroutePoint(100,50,1,2,'output_1');

or

createReroutePoint(75, 150, 2, 1, null, 'input_1');

image

jerosoler commented 3 years ago

I will look to modify the functions so that they can be added and deleted. createReroutePoint and removeReroutePoint

jerosoler commented 3 years ago

If you don't want to wait @mcantonbul

You can add a new function for example this:

editor.addReroutePoint = function(pos_x, pos_y, output_id, input_id, output_class_name, input_class_name) {

      const nodeUpdate = output_id;
      const nodeUpdateIn = input_id;
      const output_class = output_class_name;
      const input_class = input_class_name;

      const point = document.createElementNS('http://www.w3.org/2000/svg',"circle");

      point.classList.add("point");
      /*var pos_x = pos_x * ( editor.precanvas.clientWidth / (editor.precanvas.clientWidth * editor.zoom)) - (editor.precanvas.getBoundingClientRect().x * ( editor.precanvas.clientWidth / (editor.precanvas.clientWidth * editor.zoom)));
      var pos_y = pos_y * ( editor.precanvas.clientHeight / (editor.precanvas.clientHeight * editor.zoom)) - (editor.precanvas.getBoundingClientRect().y * ( editor.precanvas.clientHeight / (editor.precanvas.clientHeight * editor.zoom)));*/

      point.setAttributeNS(null, 'cx', pos_x);
      point.setAttributeNS(null, 'cy', pos_y);
      point.setAttributeNS(null, 'r', editor.reroute_width);

      const ele = document.querySelector('.connection.node_in_node-'+input_id+'.node_out_node-'+output_id+'.'+output_class+'.'+input_class);
      ele.appendChild(point);

      const nodeId = nodeUpdate;
      const searchConnection = editor.drawflow.drawflow[editor.module].data[nodeId].outputs[output_class].connections.findIndex(function(item,i) {
        return item.node == nodeUpdateIn && item.output === input_class;
      });

      if(editor.drawflow.drawflow[editor.module].data[nodeId].outputs[output_class].connections[searchConnection].points === undefined)  {
        editor.drawflow.drawflow[editor.module].data[nodeId].outputs[output_class].connections[searchConnection].points = [];
      }

      editor.drawflow.drawflow[editor.module].data[nodeId].outputs[output_class].connections[searchConnection].points.push({ pos_x: pos_x, pos_y: pos_y });
      console.log(editor.drawflow.drawflow[editor.module].data[nodeId].outputs[output_class].connections[searchConnection].points);

      editor.dispatch('addReroute', nodeId);
      editor.updateConnectionNodes('node-'+nodeUpdate);
    }

And use:

editor.addReroutePoint(800,300,7,3,'output_1', 'input_1')

Test with

editor.reroute_fix_curvature = false;
mcantonbul commented 3 years ago

Thank you so much. @jerosoler

nodegin commented 3 years ago

@jerosoler Could you please update the addReroutePoint to support when reroute_fix_curvature = true?

I am experiencing buggy reroute position when adding if reroute_fix_curvature is false (default), once reroute_fix_curvature is true, the reroute point is appended normally at the desired position on the line.

But when reroute_fix_curvature is true, using addReroutePoint to restore the data is not showing what it should be... Thanks

jerosoler commented 3 years ago

Hello @nodegin

Try

editor.addReroutePoint = function(pos_x, pos_y, output_id, input_id, output_class_name, input_class_name) {

    const nodeUpdate = output_id;
    const nodeUpdateIn = input_id;
    const output_class = output_class_name;
    const input_class = input_class_name;

    const point = document.createElementNS('http://www.w3.org/2000/svg',"circle");

    point.classList.add("point");
    /*var pos_x = pos_x * ( editor.precanvas.clientWidth / (editor.precanvas.clientWidth * editor.zoom)) - (editor.precanvas.getBoundingClientRect().x * ( editor.precanvas.clientWidth / (editor.precanvas.clientWidth * editor.zoom)));
    var pos_y = pos_y * ( editor.precanvas.clientHeight / (editor.precanvas.clientHeight * editor.zoom)) - (editor.precanvas.getBoundingClientRect().y * ( editor.precanvas.clientHeight / (editor.precanvas.clientHeight * editor.zoom)));*/

    point.setAttributeNS(null, 'cx', pos_x);
    point.setAttributeNS(null, 'cy', pos_y);
    point.setAttributeNS(null, 'r', editor.reroute_width);

    const ele = document.querySelector('.connection.node_in_node-'+input_id+'.node_out_node-'+output_id+'.'+output_class+'.'+input_class);

    let position_add_array_point = 0;
    if(editor.reroute_fix_curvature) {

        const numberPoints = ele.querySelectorAll(".main-path").length;
        var path = document.createElementNS('http://www.w3.org/2000/svg',"path");
        path.classList.add("main-path");
        path.setAttributeNS(null, 'd', '');
        ele.insertBefore(path, ele.children[numberPoints]);
        if(numberPoints === 1) {
        ele.appendChild(point);
        }  else {
        const search_point = Array.from(ele.children).indexOf(ele.children[0])
        position_add_array_point = search_point;
        ele.insertBefore(point, ele.children[search_point+numberPoints+1]);
        }

        } else {

        ele.appendChild(point);
        }

    const nodeId = nodeUpdate;
    const searchConnection = editor.drawflow.drawflow[editor.module].data[nodeId].outputs[output_class].connections.findIndex(function(item,i) {
    return item.node == nodeUpdateIn && item.output === input_class;
    });

    if(editor.drawflow.drawflow[editor.module].data[nodeId].outputs[output_class].connections[searchConnection].points === undefined)  {
    editor.drawflow.drawflow[editor.module].data[nodeId].outputs[output_class].connections[searchConnection].points = [];
    }

    if(editor.reroute_fix_curvature) {
        //console.log(position_add_array_point)
        if(position_add_array_point > 0) {
            editor.drawflow.drawflow[editor.module].data[nodeId].outputs[output_class].connections[searchConnection].points.splice(position_add_array_point, 0, { pos_x: pos_x, pos_y: pos_y });
        } else {
            editor.drawflow.drawflow[editor.module].data[nodeId].outputs[output_class].connections[searchConnection].points.push({ pos_x: pos_x, pos_y: pos_y });
        }
        ele.querySelectorAll(".main-path").forEach((item, i) => {

            item.classList.remove("selected");
        });

    } else {
        editor.drawflow.drawflow[editor.module].data[nodeId].outputs[output_class].connections[searchConnection].points.push({ pos_x: pos_x, pos_y: pos_y });

    }

        editor.dispatch('addReroute', nodeId);
        editor.updateConnectionNodes('node-'+nodeUpdate);
    }
nodegin commented 3 years ago

Hello @jerosoler , I tried your snippet but seems the lines become wrong after restore...

Before:

2021-03-17 10 42 27

After:

2021-03-17 10 42 38
jerosoler commented 3 years ago

Hello @nodegin

Try changin this line:

const search_point = Array.from(ele.children).indexOf(ele.children[0])

This line add in first position.

Try adding in the las position.

Jero

nodegin commented 3 years ago

@jerosoler Thanks! It works after changing children[0] to children[children.length - 1]