我试图将 GoJS 空间缩放简单 javascript 转换为角度指令。
这是我的Plunker
当我尝试将缩放功能复制/粘贴到指令中时,它会抛出一个错误,上面写着:
“错误:Diagram.commandHandler 值不是 CommandHandler 的实例:[object Object]”(请检查 Plunkr 控制台中的错误)
第 61 行错误
我的代码在这里:
应用程序.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;
}
});
索引.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>