Giter VIP home page Giter VIP logo

Comments (1)

WalterNorthwoods avatar WalterNorthwoods commented on May 19, 2024

The behavior is caused by Links that have their Link.adjusting property set to go.Link.End. That was intentional in that sample, so that users do not lose any of the manual reshaping of link routes just because either connected node is moved.

However, the sample could be better by only setting Link.adjusting when the link is actually reshaped -- not beforehand. Here's the updated code:

  function init() {
    if (window.goSamples) goSamples();  // init for these samples -- you don't need to call this
    var $ = go.GraphObject.make;  // for conciseness in defining templates

    myDiagram =
      new go.Diagram("myDiagramDiv",  // must name or refer to the DIV HTML element
        {
          // supply a simple narrow grid that manually reshaped link routes will follow
          grid: $(go.Panel, "Grid",
            { gridCellSize: new go.Size(8, 8) },
            $(go.Shape, "LineH", { stroke: "lightgray", strokeWidth: 0.5 }),
            $(go.Shape, "LineV", { stroke: "lightgray", strokeWidth: 0.5 })
          ),
          "draggingTool.isGridSnapEnabled": true,
          linkReshapingTool: $(SnapLinkReshapingTool),
          // when the user reshapes a Link, change its Link.routing from AvoidsNodes to Orthogonal,
          // so that combined with Link.adjusting == End the link will retain its reshaped mid points
          // even after nodes are moved
          "LinkReshaped": e => {
            e.subject.adjusting = go.Link.End;
            e.subject.routing = go.Link.Orthogonal;
          },
          "animationManager.isEnabled": false,
          "undoManager.isEnabled": true
        });

    // when the document is modified, add a "*" to the title and enable the "Save" button
    myDiagram.addDiagramListener("Modified", e => {
      var button = document.getElementById("SaveButton");
      if (button) button.disabled = !myDiagram.isModified;
      var idx = document.title.indexOf("*");
      if (myDiagram.isModified) {
        if (idx < 0) document.title += "*";
      } else {
        if (idx >= 0) document.title = document.title.slice(0, idx);
      }
    });

    // Define a function for creating a "port" that is normally transparent.
    // The "name" is used as the GraphObject.portId, the "spot" is used to control how links connect
    // and where the port is positioned on the node, and the boolean "output" and "input" arguments
    // control whether the user can draw links from or to the port.
    function makePort(name, spot, output, input) {
      // the port is basically just a small transparent square
      return $(go.Shape, "Circle",
        {
          fill: null,  // not seen, by default; set to a translucent gray by showSmallPorts, defined below
          stroke: null,
          desiredSize: new go.Size(7, 7),
          alignment: spot,  // align the port on the main Shape
          alignmentFocus: spot,  // just inside the Shape
          portId: name,  // declare this object to be a "port"
          fromSpot: spot, toSpot: spot,  // declare where links may connect at this port
          fromLinkable: output, toLinkable: input,  // declare whether the user may draw links to/from here
          cursor: "pointer"  // show a different cursor to indicate potential link point
        });
    }

    myDiagram.nodeTemplate =
      $(go.Node, "Spot",
        { locationSpot: go.Spot.Center },
        new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
        { selectable: true },
        { resizable: true, resizeObjectName: "PANEL" },
        // the main object is a Panel that surrounds a TextBlock with a Shape
        $(go.Panel, "Auto",
          { name: "PANEL" },
          new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
          $(go.Shape, "Rectangle",  // default figure
            {
              portId: "", // the default port: if no spot on link data, use closest side
              fromLinkable: true, toLinkable: true, cursor: "pointer",
              fill: "white"  // default color
            },
            new go.Binding("figure"),
            new go.Binding("fill")),
          $(go.TextBlock,
            {
              font: "bold 11pt Helvetica, Arial, sans-serif",
              margin: 8,
              maxSize: new go.Size(160, NaN),
              wrap: go.TextBlock.WrapFit,
              editable: true
            },
            new go.Binding("text").makeTwoWay())
        ),
        // four small named ports, one on each side:
        makePort("T", go.Spot.Top, false, true),
        makePort("L", go.Spot.Left, true, true),
        makePort("R", go.Spot.Right, true, true),
        makePort("B", go.Spot.Bottom, true, false),
        { // handle mouse enter/leave events to show/hide the ports
          mouseEnter: (e, node) => showSmallPorts(node, true),
          mouseLeave: (e, node) => showSmallPorts(node, false)
        }
      );

    function showSmallPorts(node, show) {
      node.ports.each(port => {
        if (port.portId !== "") {  // don't change the default port, which is the big shape
          port.fill = show ? "rgba(0,0,0,.3)" : null;
        }
      });
    }

    myDiagram.linkTemplate =
      $(go.Link,  // the whole link panel
        { relinkableFrom: true, relinkableTo: true, reshapable: true, resegmentable: true },
        {
          routing: go.Link.AvoidsNodes,  // but this is changed to go.Link.Orthgonal when the Link is reshaped
          curve: go.Link.JumpOver,
          corner: 5,
          toShortLength: 4
        },
        new go.Binding("points").makeTwoWay(),
        // remember the Link.routing too
        new go.Binding("routing", "routing", go.Binding.parseEnum(go.Link, go.Link.AvoidsNodes))
          .makeTwoWay(go.Binding.toString),
        new go.Binding("adjusting", "adjusting", go.Binding.parseEnum(go.Link, go.Link.None))
          .makeTwoWay(go.Binding.toString),
        $(go.Shape,  // the link path shape
          { isPanelMain: true, strokeWidth: 2 }),
        $(go.Shape,  // the arrowhead
          { toArrow: "Standard", stroke: null })
      );

    load();  // load an initial diagram from some JSON text

    var link = myDiagram.links.first();
    if (link) link.isSelected = true;

    // initialize the Palette that is on the left side of the page
    myPalette =
      new go.Palette("myPaletteDiv",  // must name or refer to the DIV HTML element
        {
          maxSelectionCount: 1,
          nodeTemplateMap: myDiagram.nodeTemplateMap,  // share the templates used by myDiagram
          model: new go.GraphLinksModel([  // specify the contents of the Palette
            { text: "Start", figure: "Circle", fill: "green" },
            { text: "Step" },
            { text: "DB", figure: "Database", fill: "lightgray" },
            { text: "???", figure: "Diamond", fill: "lightskyblue" },
            { text: "End", figure: "Circle", fill: "red" },
            { text: "Comment", figure: "RoundedRectangle", fill: "lightyellow" }
          ])
        });

    document.getElementById("AvoidsNodesCheckBox").onclick = e => {
      myDiagram.toolManager.linkReshapingTool.avoidsNodes = e.target.checked;
    }
  }


  // Show the diagram's model in JSON format that the user may edit
  function save() {
    saveDiagramProperties();  // do this first, before writing to JSON
    document.getElementById("mySavedModel").value = myDiagram.model.toJson();
    myDiagram.isModified = false;
  }
  function load() {
    myDiagram.model = go.Model.fromJson(document.getElementById("mySavedModel").value);
    loadDiagramProperties();
  }

  function saveDiagramProperties() {
    myDiagram.model.modelData.position = go.Point.stringify(myDiagram.position);
  }
  // Called by "InitialLayoutCompleted" DiagramEvent listener, NOT directly by load()!
  function loadDiagramProperties(e) {
    // set Diagram.initialPosition, not Diagram.position, to handle initialization side-effects
    var pos = myDiagram.model.modelData.position;
    if (pos) myDiagram.initialPosition = go.Point.parse(pos);
  }
  window.addEventListener('DOMContentLoaded', init);

Also I have cleaned up the initial link data object in the model:

  "linkDataArray": [
{"from":-10, "to":-11, "fromPort":"R", "toPort":"L", "points":[121,240,131,240,132,240,132,240,216,240,216,176,264,176,264,104,392,104,392,240,480,240,480,280,501,280,511,280]}
  ]

from gojs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.