gojs实现时序图效果代码

代码语言:html

所属分类:图表

代码描述:gojs实现时序图效果代码

代码标签: gojs 时序图

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
</head>

<body>
    <script src="//repo.bfw.wiki/bfwrepo/js/go.js"></script>
  <div id="allSampleContent" class="p-4 w-full">
  <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro" rel="stylesheet" type="text/css">
    <script id="code">
    function init() {

      // Since 2.2 you can also author concise templates with method chaining instead of GraphObject.make
      // For details, see https://gojs.net/latest/intro/buildingObjects.html
      const $ = go.GraphObject.make;

      myDiagram =
        $(go.Diagram, "myDiagramDiv", // must be the ID or reference to an HTML DIV
          {
            allowCopy: false,
            linkingTool: $(MessagingTool),  // defined below
            "resizingTool.isGridSnapEnabled": true,
            draggingTool: $(MessageDraggingTool),  // defined below
            "draggingTool.gridSnapCellSize": new go.Size(1, MessageSpacing / 4),
            "draggingTool.isGridSnapEnabled": true,
            // automatically extend Lifelines as Activities are moved or resized
            "SelectionMoved": ensureLifelineHeights,
            "PartResized": ensureLifelineHeights,
            "undoManager.isEnabled": true
          });

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

      // define the Lifeline Node template.
      myDiagram.groupTemplate =
        $(go.Group, "Vertical",
          {
            locationSpot: go.Spot.Bottom,
            locationObjectName: "HEADER",
            minLocation: new go.Point(0, 0),
            maxLocation: new go.Point(9999, 0),
            selectionObjectName: "HEADER"
          },
          new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
          $(go.Panel, "Auto",
            { name: "HEADER" },
            $(go.Shape, "Rectangle",
              {
                fill: $(go.Brush, "Linear", { 0: "#bbdefb", 1: go.Brush.darkenBy("#bbdefb", 0.1) }),
                stroke: null
              }),
            $(go.TextBlock,
              {
                margin: 5,
                font: "400 10pt Source Sans Pro, sans-serif"
              },
              new go.Binding("text", "text"))
          ),
          $(go.Shape,
            {
              figure: "LineV",
              fill: null,
              stroke: "gray",
              strokeDashArray: [3, 3],
              width: 1,
              alignment: go.Spot.Center,
              portId: "",
              fromLinkable: true,
              fromLinkableDuplicates: true,
              toLinkable: true,
              toLinkableDuplicates: true,
              cursor: "pointer"
            },
            new go.Binding("height", "duration", computeLifelineHeight))
        );

      // define the Activity Node template
      myDiagram.nodeTemplate =
        $(go.Node,
          {
            locationSpot: go.Spot.Top,
            locationObjectName: "SHAPE",
            minLocation: new go.Point(NaN, LinePrefix - ActivityStart),
            maxLocation: new go.Point(NaN, 19999),
            selectionObjectName: "SHAPE",
            resizable: true,
            resizeObjectName: "SHAPE",
            resizeAdornmentTemplate:
              $(go.Adornment, "Spot",
                $(go.Placeholder),
                $(go.Shape,  // only a bottom resize handle
                  {
                    alignment: go.Spot.Bottom, cursor: "col-resize",
                    desiredSize: new go.Size(6, 6), fill: "yellow"
                  })
              )
          },
          new go.Binding("location", "", computeActivityLocation).makeTwoWay(backComputeActivityLocation),
          $(go.Shape, "Rectangle",
            {
              name: "SHAPE",
              fill: "white", stroke: "black",
              width: ActivityWidth,
              // allow Activities to be resized down to 1/4 of a time unit
              minSize: new go.Size(ActivityWidth, computeActivityHeight(0.25))
            },
            new go.Binding("height", "duration", computeActivityHeight).makeTwoWay(backComputeActivityHeight))
        );

      // define the Message Link template.
      myDiagram.linkTemplate =
        $(MessageLink,  // defined below
          { selectionAdorned: true, curviness: 0 },
          $(go.Shape, "Rectangle",
            { stroke: "black" }),
          $(go.Shape,
            { toArrow: "OpenTriangle", stroke: "black" }),
          $(go.TextBlock,
            {
              font: "400 9pt Source Sans Pro, sans-serif",
              segmentIndex: 0,
              segmentOffset: new go.Point(NaN, NaN),
              isMultiline: false,
              editable: true
            },
            new go.Binding("text", "text").makeTwoWay())
        );

      // create the graph by reading the JSON data saved in "mySavedModel" textarea element
      load();
    }

    function ensureLifelineHeights(e) {
      // iterate over all Activities (ignore Groups)
      const arr = myDiagram.model.nodeDataArray;
      let max = -1;
      for (let i = 0; i < arr.length; i++) {
        const act = arr[i];
        if (act.isGroup) continue;
        max = Math.max(max, act.start + act.duration);
      }
      if (max > 0) {
        // now iterate over only Groups
        for (let i = 0; i < arr.length; i++) {
          const gr = arr[i];
          if (!gr.isGroup) continue;
          if (max > gr.duration) {  // this only extends, never shrinks
            myDiagram.model.setDataProperty(gr, "duration", max);
          }
        }
      }
    }

    // some parameters
    const LinePrefix = 20;  // vertical starting point in document for all Messages and Activations
    const LineSuffix = 30;  // vertical length beyond the last message time
    const MessageSpacing = 20;  // vertical distance between Messages at different steps
    const ActivityWidth = 10;  // width of each vertical activity bar
    const ActivityStart = 5;  // height before start message time
    const ActivityEnd = 5;  // height beyond end message time

    function computeLifelineHeight(duration) {
      return LinePrefix + duration * MessageSpacing + LineSuffix;
    }

    function computeActivityLocation(act) {
      const groupdata = myDiagram.model.findNodeDataForKey(act.group);
      if (groupdata === null) return new go.Point();
      // get location of Lifeline's starting point
      const grouploc = go.Point.parse(groupdata.loc);
      return new go.Point(grouploc.x, convertTimeToY(act.start) - ActivityStart);
    }
    function backComputeActivityLocation(loc, act) {
      myDiagram.model.setDataProperty(act, "start", convertYToTime(loc.y + ActivityStart));
    }

    function computeActivityHeight(duration) {
      return ActivityStart + duration * MessageSpacing + ActivityEnd;
    }
    function backComputeActivityHeight(height) {
      return (height - ActivityStart - ActivityEnd) / MessageSpacing;
    }

    // time is just an abstract small non-negative integer
    // here we map between an abstract time and a vertical position
    function convertTimeToY(t) {
      return t * MessageSpacing + LinePrefix;
    }
    function convertYToTime(y) {
      return (y - LinePrefix) / MessageSpacing;
    }


  // a custom routed Link
  class MessageLink extends go.Link {
    constructor() {
      super();
      this.time = 0;  // use this "time" value when this is the temporaryLink
    }

    getLinkPoint(node, port, spot, from, ortho, othernode, otherport) {
      const p = port.getDocumentPoint(go.Spot.Center);
      const r = port.getDocumentBounds();
      const op = otherport.getDocumentPoint(go.Spot.Center);

      const data = this.data;
      const time = data !== null ? data.time : this.time;  // if not bound, assume this has its own "time" property

      const aw = this.findActivityWidth(node, time);
      const x = (op.x > p.x ? p.x + aw / 2 : p.x - aw / 2);
      const y = convertTimeToY(time);
      return new go.Point(x, y);
    }

    findActivityWidth(node, time) {
      let aw = ActivityWidth;
      if (node instanceof go.Group) {
        // see if there is an Activity Node at this point -- if not, connect the link directly with the Group's l.........完整代码请登录后点击上方下载按钮下载查看

网友评论0