将缩放功能复制/粘贴到指令时出错

时间:2017-10-03 19:54:38

标签: javascript angularjs angular-directive gojs angular-directive-link

我试图将GoJS空间缩放简单的javascript转换为角度指令。

这是我的Plunker

当我尝试将缩放功能复制/粘贴到指令中时 抛出错误说:

  

“错误:Diagram.commandHandler值为   不是CommandHandler的实例:[object Object]“(请检查   Plunkr控制台中的错误)

     

第61行错误

我的代码在这里:

app.js

var app = angular.module('app', []);

app.directive('goDiagram', function($http) {
  return {
    restrict: 'E',
    template: '<div></div>',
    replace: true,
    scope: {
      model: '=goModel'
    },
    link: function(scope, element, attrs) {
      if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
      var $ = go.GraphObject.make;
      var rainbow = $(go.Brush, "Linear", {
        0: "red",
        1: "green"
      });
      var diagram = $(go.Diagram, element[0], {
        nodeTemplate: $(go.Node, "Auto", {
            locationSpot: go.Spot.Center
          }, {
            width: 120,
            height: 15,
            locationSpot: go.Spot.Center
          },
          new go.Binding("location"),
          $(go.Shape, {
            fill: "#e74c3c",
            stroke: '#c0392b'
          }, {
            portId: "",
            cursor: "pointer",
            strokeWidth: 0,
          }),
          $(go.TextBlock, {
              margin: 0,
              stroke: "#eee"
            },
            new go.Binding("text", "key")
          )
        ),
        linkTemplate: $(go.Link, {
            // routing: go.Link.AvoidsNodes,
            reshapable: true,
            resegmentable: true
          },
          $(go.Shape, {
              strokeWidth: 3,
              stroke: rainbow
            },
            // new go.Binding("stroke", rainbow),
          ),
          $(go.Shape, {
            toArrow: "Standard"
          }),
        ),
        // For Zoom
        initialContentAlignment: go.Spot.Center, // center the content
        commandHandler: $(SpacingCommandHandler),
        // update the SpacingCommandHandler.space from the model at the end of each transaction
        "ModelChanged": function(e) {
          if (e.isTransactionFinished) {
            myDiagram.commandHandler.space = myDiagram.model.modelData.space;
          }
        },
        "undoManager.isEnabled": true // enable undo & redo
      });

      // Conversion functions -- these only work with myDiagram, assuming it uses a SpacingCommandHandler

      function spacedLocationParse(str) {
        var cmd = myDiagram.commandHandler;
        if (!(cmd instanceof SpacingCommandHandler)) throw new Error("not using SpacingCommandHandler");
        var pt = go.Point.parse(str);
        pt.x = (pt.x - cmd.spaceCenter.x) * cmd.space + cmd.spaceCenter.x;
        if (cmd.isYSpaced) {
          pt.y = (pt.y - cmd.spaceCenter.y) * cmd.space + cmd.spaceCenter.y;
        }
        return pt;
      }

      function spacedLocationStringify(pt, data) {
        var cmd = myDiagram.commandHandler;
        if (!cmd._isUpdating) {
          pt = pt.copy();
          pt.x = (pt.x - cmd.spaceCenter.x) / cmd.space + cmd.spaceCenter.x;
          if (cmd.isYSpaced) {
            pt.y = (pt.y - cmd.spaceCenter.y) / cmd.space + cmd.spaceCenter.y;
          }
          return go.Point.stringify(pt);
        } else {
          return data.loc;
        }
      }


      // The custom CommandHandler that avoids changing the Diagram.scale
      function SpacingCommandHandler() {
        go.CommandHandler.call(this);
        this._space = 1.0; // replaces Diagram.scale; also copied to/from Model.modelData.space
        this._spaceCenter = new go.Point(0, 0); // not currently used -- should this be saved on modelData too?
        this._isYSpaced = true; // scale Y along with X?  This option is just for demonstration purposes.
        this._isUpdating = false;
      }
      go.Diagram.inherit(SpacingCommandHandler, go.CommandHandler);

      // Overrides of commands that scale the diagram -- change the space instead

      /** @override */
      SpacingCommandHandler.prototype.decreaseZoom = function(factor) {
        if (factor === undefined /*notpresent*/ ) factor = 1.0 / this.zoomFactor;
        this.setSpace(this.space * factor);
      };
      /** @override */
      SpacingCommandHandler.prototype.canDecreaseZoom = function(factor) {
        if (factor === undefined /*notpresent*/ ) factor = 1.0 / this.zoomFactor;
        return this.checkSpace(this.space * factor);
      };

      /** @override */
      SpacingCommandHandler.prototype.increaseZoom = function(factor) {
        if (factor === undefined /*notpresent*/ ) factor = 1.0 / this.zoomFactor;
        this.setSpace(this.space / factor);
      };
      /** @override */
      SpacingCommandHandler.prototype.canIncreaseZoom = function(factor) {
        if (factor === undefined /*notpresent*/ ) factor = 1.0 / this.zoomFactor;
        return this.checkSpace(this.space / factor);
      };

      /** @override */
      SpacingCommandHandler.prototype.resetZoom = function(newspace) {
        if (newspace === undefined /*notpresent*/ ) newspace = 1.0;
        this.setSpace(newspace);
      };
      /** @override */
      SpacingCommandHandler.prototype.canResetZoom = function(newspace) {
        return this.checkSpace(newspace);
      };

      // actually set a new value for SPACE
      SpacingCommandHandler.prototype.setSpace = function(s) {
        this.space = Math.max(0.1, Math.min(10.0, s));
      };

      // validity check for a new value for SPACE
      SpacingCommandHandler.prototype.checkSpace = function(s) {
        return 0.1 <= s && s <= 10.0;
      };


      // Properties for SpacingCommandHandler

      Object.defineProperty(SpacingCommandHandler.prototype, "space", {
        get: function() {
          return this._space;
        },
        set: function(val) {
          if (val !== this._space) {
            this._space = val;
            var diagram = this.diagram;
            if (diagram !== null) { // store in model too, and support undo
              diagram.model.setDataProperty(diagram.model.modelData, "space", val);
            }
            this.updateAllLocations();
            // update the page showing the current value
            document.getElementById("SPACE").textContent = val.toString();
          }
        }
      });

      Object.defineProperty(SpacingCommandHandler.prototype, "spaceCenter", {
        get: function() {
          return this._spaceCenter;
        },
        set: function(val) {
          if (!val.equals(this._spaceCenter)) {
            this._spaceCenter = val.copy();
          }
        }
      });

      Object.defineProperty(SpacingCommandHandler.prototype, "isYSpaced", {
        get: function() {
          return this._isYSpaced;
        },
        set: function(val) {
          if (val !== this._isYSpaced) {
            this._isYSpaced = val;
            this.updateAllLocations();
          }
        }
      }); 

      // If the spacing or isYSpaced properties change value,
      // we need to update the effective locations of all nodes.
      // Assume Node.location is data bound to "loc" property.
      SpacingCommandHandler.prototype.updateAllLocations = function() {
        var diagram = this.diagram;
        if (diagram === null) return;
        this._isUpdating = true;
        diagram.skipsUndoManager = true;
        diagram.startTransaction("respace nodes");
        diagram.parts.each(function(p) {
          p.updateTargetBindings("loc");
        });
        diagram.nodes.each(function(n) {
          n.updateTargetBindings("loc");
        });
        diagram.commitTransaction("respace nodes");
        diagram.skipsUndoManager = false;
        this._isUpdating = false;
      };
      // end SpacingCommandHandler class

      function updateAngular(e) {
        if (e.isTransactionFinished) {
          scope.$apply();
        }
      }

      function updateSelection(e) {
        diagram.model.selectedNodeData = null;
        var it = diagram.selection.iterator;
        while (it.next()) {
          var selnode = it.value;
          // ignore a selected link or a deleted node
          if (selnode instanceof go.Node && selnode.data !== null) {
            diagram.model.selectedNodeData = selnode.data;
            break;
          }
        }
        scope.$apply();
      }
      // watch scope
      scope.$watch("model", function(newmodel) {
        if (newmodel != undefined) {
          var oldmodel = diagram.model;
          if (oldmodel !== newmodel) {
            diagram.removeDiagramListener("ChangedSelection", updateSelection);
            diagram.model = newmodel;
            diagram.addDiagramListener("ChangedSelection", updateSelection);
          }
        }
      });
    }
  }
});

app.controller('appController', function($scope) {
  $scope.init = function(d) {
    $scope.hello = "Hello Plunker!!!!";
    $scope.model = new go.GraphLinksModel(
      [{
        key: "Alpha",
        color: "lightblue",
        location: new go.Point(150, 130),
        loc: "150 130"
      }, {
        key: "Beta",
        color: "orange",
        location: new go.Point(350, 180),
        loc: "350 180"
      }, {
        key: "Gamma",
        color: "lightgreen",
        location: new go.Point(150, 230),
        loc: "150 230"
      }, {
        key: "Delta",
        color: "pink",
        location: new go.Point(250, 330),
        loc: "250 330"
      }], [{
        from: "Alpha",
        to: "Beta",
        inColor: "red",
        outColor: "blue"
      }, {
        from: "Alpha",
        to: "Gamma",
        inColor: "yellow",
        outColor: "blue"
      }, {
        from: "Beta",
        to: "Gamma",
        inColor: "green",
        outColor: "pink"
      }, {
        from: "Gamma",
        to: "Delta",
        inColor: "black",
        outColor: "red"
      }, {
        from: "Delta",
        to: "Alpha",
        inColor: "violet",
        outColor: "green"
      }]);
    $scope.model.selectedNodeData = null;
  }
});

的index.html

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="angular.js@1.5.10" data-semver="1.5.10" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.10/angular.min.js"></script>
    <script data-require="angular-route@1.5.8" data-semver="1.5.8" src="https://code.angularjs.org/1.5.8/angular-route.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="https://gojs.net/latest/release/go.js"></script>
    <script src="script.js"></script>
  </head>

  <body ng-controller="appController">
    <div ng-init="init()">
      <h1>{{hello}}</h1>
      <go-diagram go-model="model" style="border: solid 1px black; width:100%; height:400px"></go-diagram>
    </div>
  </body>

</html>

1 个答案:

答案 0 :(得分:0)

我建议尝试覆盖图CommandHandler的实例上的方法,而不是尝试子类化CommandHandler。 https://gojs.net/latest/intro/extensions.html#OverridingMethodWithoutDefiningSubclass

在角度指令

// create the diagram (line 20 in your Plunkr)
var diagram =
    $(go.Diagram, element[0], {
      // diagram settings
      // ...
      // more diagram settings
    });

// then get a reference to the diagram's CommandHandler, you can call it SpacingCommandHandler instead of tool if you like.
var tool = diagram.commandHandler;

// then you can override a function of the CommandHandler like so:
tool.decreaseZoom = function() {
    console.log('my decrease zoom function!');
    // Maybe do something else before
    // ...

    // Be careful about using 'this' within such functions!

    // In cases where you want normal behavior, call the base functionality
    // Note the reference to the prototype
    // and the call to 'call' passing it what 'this' should be.
    go.CommandHandler.prototype.decreaseZoom.call(tool);

    // Maybe do something else after
    // ...
}

当我需要在我自己的angular指令中扩展CommandHandler.deleteSelection时,我成功地使用了这种方法。使用这种方法,你应该让你超越你的错误。