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=Lato:300,400,700" rel="stylesheet" type="text/css">
    <script id="code">

  // define a custom grid layout that makes sure the length of each lane is the same
  // and that each lane is broad enough to hold its subgraph
  class PoolLayout extends go.GridLayout {
    constructor() {
      super();
      this.MINLENGTH = 200;  // this controls the minimum length of any swimlane
      this.MINBREADTH = 100;  // this controls the minimum breadth of any non-collapsed swimlane
      this.cellSize = new go.Size(1, 1);
      this.wrappingColumn = Infinity;
      this.wrappingWidth = Infinity;
      this.spacing = new go.Size(0, 0);
      this.alignment = go.GridLayout.Position;
    }

    doLayout(coll) {
      const diagram = this.diagram;
      if (diagram === null) return;
      diagram.startTransaction("PoolLayout");
      // make sure all of the Group Shapes are big enough
      const minlen = this.computeMinPoolLength();
      diagram.findTopLevelGroups().each(lane => {
        if (!(lane instanceof go.Group)) return;
        const shape = lane.selectionObject;
        if (shape !== null) {  // change the desiredSize to be big enough in both directions
          const sz = this.computeLaneSize(lane);
          shape.width = (!isNaN(shape.width)) ? Math.max(shape.width, sz.width) : sz.width;
          // if you want the height of all of the lanes to shrink as the maximum needed height decreases:
          shape.height = minlen;
          // if you want the height of all of the lanes to remain at the maximum height ever needed:
          //shape.height = (isNaN(shape.height) ? minlen : Math.max(shape.height, minlen));
          const cell = lane.resizeCellSize;
          if (!isNaN(shape.width) && !isNaN(cell.width) && cell.width > 0) shape.width = Math.ceil(shape.width / cell.width) * cell.width;
          if (!isNaN(shape.height) && !isNaN(cell.height) && cell.height > 0) shape.height = Math.ceil(shape.height / cell.height) * cell.height;
        }
      });
      // now do all of the usual stuff, according to whatever properties have been set on this GridLayout
      super.doLayout(coll);
      diagram.commitTransaction("PoolLayout");
    };

    // compute the minimum length of the whole diagram needed to hold all of the Lane Groups
    computeMinPoolLength() {
      let len = this.MINLENGTH;
      myDiagram.findTopLevelGroups().each(lane => {
        const holder = lane.placeholder;
        if (holder !== null) {
          const sz = holder.actualBounds;
          len = Math.max(len, sz.height);
        }
      });
      return len;
    }

    // compute the minimum size for a particular Lane Group
    computeLaneSize(lane) {
      // assert(lane instanceof go.Group);
      const sz = new go.Size(lane.isSubGraphExpanded ? this.MINBREADTH : 1, this.MINLENGTH);
      if (lane.isSubGraphExpanded) {
        const holder = lane.placeholder;
        if (holder !== null) {
          const hsz = holder.actualBounds;
          sz.width = Math.max(sz.width, hsz.width);
        }
      }
      // minimum breadth needs to be big enough to hold the header
      const hdr = lane.findObject("HEADER");
      if (hdr !== null) sz.width = Math.max(sz.width, hdr.actualBounds.width);
      return sz;
    }
  }
  // end PoolLayout class


    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",
          {
            // make sure the top-left corner of the viewport is occupied
            contentAlignment: go.Spot.TopLeft,
            // use a simple layout to stack the top-level Groups next to each other
            layout: $(PoolLayout),
            // disallow nodes to be dragged to the diagram's background
            mouseDrop: e => {
              e.diagram.currentTool.doCancel();
            },
            // a clipboard copied node is pasted into the original node's group (i.e. lane).
            "commandHandler.copiesGroupKey": true,
            // automatically re-layout the swim lanes after dragging the selection
            "SelectionMoved": relayoutDiagram,  // this DiagramEvent listener is
            "SelectionCopied": relayoutDiagram, // defined above
            "undoManager.isEnabled": true,
            // allow TextEditingTool to start without selecting first
            "textEditingTool.starting": go.TextEditingTool.SingleClick
          });

      // Customize the dragging tool:
      // When dragging a node set its opacity to 0.6 and move it to be in front of other nodes
      myDiagram.toolManager.draggingTool.doActivate = function() {
        go.DraggingTool.prototype.doActivate.call(this);
        this.currentPart.opacity = 0.6;
        this.currentPart.layerName = "Foreground";
      }
      myDiagram.toolManager.draggingTool.doDeactivate = function() {
        this.currentPart.opacity = 1;
        this.currentPart.layerName = "";
        go.DraggingTool.prototype.doDeactivate.call(this);
      }

      // this is called after nodes have been moved
      function relayoutDiagram() {
        myDiagram.selection.each(n => n.invalidateLayout());
        myDiagram.layoutDiagram();
      }

      // There are only three note colors by default, blue, red, and yellow but you could add more here:
      const noteColors = ['#009CCC', '#CC293D', '#FFD700'];
      function getNoteColor(num) {
        return noteColors[Math.min(num, noteColors.length - 1)];
      }

      myDiagram.nodeTemplate =
        $(go.Node, "Horizontal",
          new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
          $(go.Shape, "Rectangle", {
            fill: '#009CCC', strokeWidth: 1, stroke: '#009CCC',
            width: 6, stretch: go.GraphObject.Vertical, alignment: go.Spot.Left,
            // if a user clicks the colored portion of a node, cycle through colors
            click: (e, obj) => {
              myDiagram.startTransaction("Update node color");
              let newColor = parseInt(obj.part.data.color) + 1;
              if (newColor > noteColors.length - 1) newColor = 0;
              myDiagram.model.setDataProperty(obj.part.data, "color", newColor);
              myDiagram.commitTransaction("Update node color");
            }
          },
            new go.Binding("fill", "color", getNoteColor),
            new go.Binding("stroke", "color", getNoteColor)
          ),
          $(go.Panel, "Auto",
            $(go.Shape, "Rectangle", { fill: "white", stroke: '#CCCCCC' }),
            $(go.Panel, "Table",
              { width: 130, minSize: new go.Size(NaN, 50) },
              $(go.TextBlock,
                {
                  name: 'TEXT',
                  margin: 6, font: '11px Lato, sans-serif', editable: true,
                  stroke: "#000", maxSize: new go.Size(130, NaN),
                  alignment: go.Spot.TopLeft
                },
                new go.Binding("text", "text").makeTwoWay())
            )
          )
        );

      // unmovable node that acts as a button
      myDiagram.nodeTemplateMap.add('newbutton',
        $(go.Node, "Horizontal",
          new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
          {
            selectable: false,
            click: (e, node) => {
              myDiagram.startTransaction('add node');
              const newdata = { group: "Problems", loc: "0 50", text: "New item " + node.containingGroup.memberParts.count, color: 0 };
              myDiagram.model.addNodeData(newdata);
              myDiagram.commitTransaction('add node');
              const newnode = myDiagram.findNodeForData(newdata);
              myDiagram.select(newnode);
              myDiagram.commandHandler.editTextBlock();
            },
            background: 'white'
          },
          $(go.Panel, "Auto",
            $(go.Shape, "Rectangle", { strokeWidth: 0, stroke: null, fill: '#6FB583' }),
            $(go.Shape, "PlusLine", { margin: 6, strokeWidth: 2, width: 12, height: 12, stroke: 'white', background: '#6FB583' })
          ),
          $(go.TextBlock, "New item", { font: '10px Lato, sans-serif', margin: 6, })
        )
      );

      // While dragging, highlight the dragged-over group
      function highlightGroup(grp, show) {
        if (show) {
          const part = myDiagram.toolManager.draggingTool.currentPart;
          if (part.containingGroup !== grp) {
            grp.isHighlighted = true;
            return;
          }
        }
        grp.isHighlighted = false;
      }

      myDiagram.groupTemplate =
        $(go.Group, "Vertical",
          {
            selectable: false,
            selectionObjectName: "SHAPE", // even though its not selectable, this is used in the layout
            layerName: "Background",  // all lanes are always behind all nodes and links
            layout: $(go.GridLayout,  // automatically lay out the lane's subgraph
              {
                wrappingColumn: 1,
                cellSize: new go.Size(1, 1),
                spacing: new go.Size(5, 5),
                alignment: go.GridLayout.Position,
                comparer: (a, b) => {  // can re-order tasks within a lane
                  const ay = a.location.y;
                  const by = b.location.y;
                  if (isNaN(ay) || isNaN(by)) return 0;
                  if (ay < by) return -1;
                  if (ay > by) return 1;
                  return 0;
                }
              }),
            click: (e, grp) => {  // allow simple click on group to clear selection
              if (!e.shift && !e.control && !e.meta) e.diagram.clearSelection();
            },
            computesBoundsAfterDrag: true,  // needed to prevent recomputing Group.placeholder bounds too soon
            handlesDragDropForMembers: true,  // don't need to define handlers on member Nodes and Links
            mouseDragEnter: (e, grp, prev) => highlightGroup(grp, true),
            mouseDragLeave: (e, grp, next) => highlightGroup(grp, false),
            mouseDrop: (e, grp) => {  // dropping a copy of some Nodes and Links onto this Group adds them to this .........完整代码请登录后点击上方下载按钮下载查看

网友评论0