Commit fff3af96 by jlc

update:移动拖拽节点

parent f93688f4
......@@ -8,10 +8,12 @@
"name": "vue3-ts-gojs",
"version": "0.0.0",
"dependencies": {
"uuid": "^10.0.0",
"vue": "^3.4.21"
},
"devDependencies": {
"@types/jquery": "^3.5.30",
"@types/uuid": "^10.0.0",
"@vitejs/plugin-vue": "^5.0.4",
"gojs": "^3.0.3",
"typescript": "^5.4.5",
......@@ -632,6 +634,12 @@
"integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==",
"dev": true
},
"node_modules/@types/uuid": {
"version": "10.0.0",
"resolved": "https://registry.npmmirror.com/@types/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
"dev": true
},
"node_modules/@vitejs/plugin-vue": {
"version": "5.0.4",
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
......@@ -1053,6 +1061,18 @@
"node": ">=14.17"
}
},
"node_modules/uuid": {
"version": "10.0.0",
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/vite": {
"version": "5.2.12",
"resolved": "https://registry.npmmirror.com/vite/-/vite-5.2.12.tgz",
......
......@@ -9,10 +9,12 @@
"preview": "vite preview"
},
"dependencies": {
"uuid": "^10.0.0",
"vue": "^3.4.21"
},
"devDependencies": {
"@types/jquery": "^3.5.30",
"@types/uuid": "^10.0.0",
"@vitejs/plugin-vue": "^5.0.4",
"gojs": "^3.0.3",
"typescript": "^5.4.5",
......
......@@ -11,7 +11,8 @@
<!-- <panel></panel> -->
<!-- <contextMenu></contextMenu> -->
<!-- <firstProject></firstProject> -->
<port></port>
<!-- <port></port> -->
<imageNode></imageNode>
</template>
<script setup lang="ts">
......@@ -27,7 +28,8 @@
// import panel from './components/panel.vue';
// import contextMenu from './components/contextMenu.vue';
// import firstProject from './stageAchievements/firstProject.vue';
import port from './components/port.vue';
// import port from './components/port.vue';
import imageNode from './stageAchievements/imageNode.vue';
</script>
<style scoped>
......
/*
* Copyright (C) 1998-2024 by Northwoods Software Corporation. All Rights Reserved.
*/
/*
* This is an extension and not part of the main GoJS library.
* Note that the API for this class may change with any version, even point releases.
* If you intend to use an extension in production, you should copy the code to your own source directory.
* Extensions can be found in the GoJS kit under the extensions or extensionsJSM folders.
* See the Extensions intro page (https://gojs.net/latest/intro/extensions.html) for more information.
*/
import * as go from 'gojs';
/**
* The GuidedDraggingTool class makes guidelines visible as the parts are dragged around a diagram
* when the selected part is nearly aligned with another part.
*
* If you want to experiment with this extension, try the <a href="../../samples/GuidedDragging.html">Guided Dragging</a> sample.
* @category Tool Extension
*/
export class GuidedDraggingTool extends go.DraggingTool {
// horizontal guidelines
guidelineHtop: go.Part;
guidelineHbottom: go.Part;
guidelineHcenter: go.Part;
// vertical guidelines
guidelineVleft: go.Part;
guidelineVright: go.Part;
guidelineVcenter: go.Part;
// properties that the programmer can modify
private _guidelineSnapDistance: number;
private _isGuidelineEnabled: boolean;
private _horizontalGuidelineColor: string;
private _verticalGuidelineColor: string;
private _centerGuidelineColor: string;
private _guidelineWidth: number;
private _searchDistance: number;
private _isGuidelineSnapEnabled: boolean;
/**
* Constructs a GuidedDraggingTool and sets up the temporary guideline parts.
*/
constructor(init?: Partial<GuidedDraggingTool>) {
super();
this.name = 'GuidedDragging';
this._guidelineSnapDistance = 6;
this._isGuidelineEnabled = true;
this._horizontalGuidelineColor = 'gray';
this._verticalGuidelineColor = 'gray';
this._centerGuidelineColor = 'gray';
this._guidelineWidth = 1;
this._searchDistance = 1000;
this._isGuidelineSnapEnabled = true;
const partProperties = { layerName: 'Tool', isInDocumentBounds: false };
const shapeProperties = { stroke: 'gray', isGeometryPositioned: true };
// temporary parts for horizonal guidelines
this.guidelineHtop = new go.Part(partProperties).add(
new go.Shape(shapeProperties).set({ geometryString: 'M0 0 100 0' })
);
this.guidelineHbottom = new go.Part(partProperties).add(
new go.Shape(shapeProperties).set({ geometryString: 'M0 0 100 0' })
);
this.guidelineHcenter = new go.Part(partProperties).add(
new go.Shape(shapeProperties).set({ geometryString: 'M0 0 100 0' })
);
// temporary parts for vertical guidelines
this.guidelineVleft = new go.Part(partProperties).add(
new go.Shape(shapeProperties).set({ geometryString: 'M0 0 0 100' })
);
this.guidelineVright = new go.Part(partProperties).add(
new go.Shape(shapeProperties).set({ geometryString: 'M0 0 0 100' })
);
this.guidelineVcenter = new go.Part(partProperties).add(
new go.Shape(shapeProperties).set({ geometryString: 'M0 0 0 100' })
);
if (init) Object.assign(this, init);
}
/**
* Gets or sets the margin of error for which guidelines show up.
*
* The default value is 6.
* Guidelines will show up when the aligned nodes are ± 6px away from perfect alignment.
*/
get guidelineSnapDistance(): number {
return this._guidelineSnapDistance;
}
set guidelineSnapDistance(val: number) {
if (typeof val !== 'number' || isNaN(val) || val < 0) throw new Error('new value for GuidedDraggingTool.guidelineSnapDistance must be a non-negative number');
this._guidelineSnapDistance = val;
}
/**
* Gets or sets whether the guidelines are enabled or disables.
*
* The default value is true.
*/
get isGuidelineEnabled(): boolean {
return this._isGuidelineEnabled;
}
set isGuidelineEnabled(val: boolean) {
if (typeof val !== 'boolean') throw new Error('new value for GuidedDraggingTool.isGuidelineEnabled must be a boolean value.');
this._isGuidelineEnabled = val;
}
/**
* Gets or sets the color of horizontal guidelines.
*
* The default value is "gray".
*/
get horizontalGuidelineColor(): string {
return this._horizontalGuidelineColor;
}
set horizontalGuidelineColor(val: string) {
if (this._horizontalGuidelineColor !== val) {
this._horizontalGuidelineColor = val;
if (this.guidelineHbottom) {
(this.guidelineHbottom.elements.first() as go.Shape).stroke = this._horizontalGuidelineColor;
}
if (this.guidelineHtop) {
(this.guidelineHtop.elements.first() as go.Shape).stroke = this._horizontalGuidelineColor;
}
}
}
/**
* Gets or sets the color of vertical guidelines.
*
* The default value is "gray".
*/
get verticalGuidelineColor(): string {
return this._verticalGuidelineColor;
}
set verticalGuidelineColor(val: string) {
if (this._verticalGuidelineColor !== val) {
this._verticalGuidelineColor = val;
if (this.guidelineVleft) {
(this.guidelineVleft.elements.first() as go.Shape).stroke = this._verticalGuidelineColor;
}
if (this.guidelineVright) {
(this.guidelineVright.elements.first() as go.Shape).stroke = this._verticalGuidelineColor;
}
}
}
/**
* Gets or sets the color of center guidelines.
*
* The default value is "gray".
*/
get centerGuidelineColor(): string {
return this._centerGuidelineColor;
}
set centerGuidelineColor(val: string) {
if (this._centerGuidelineColor !== val) {
this._centerGuidelineColor = val;
if (this.guidelineVcenter) {
(this.guidelineVcenter.elements.first() as go.Shape).stroke = this._centerGuidelineColor;
}
if (this.guidelineHcenter) {
(this.guidelineHcenter.elements.first() as go.Shape).stroke = this._centerGuidelineColor;
}
}
}
/**
* Gets or sets the strokeWidth of the guidelines.
*
* The default value is 1.
*/
get guidelineWidth(): number {
return this._guidelineWidth;
}
set guidelineWidth(val: number) {
if (typeof val !== 'number' || isNaN(val) || val < 0) throw new Error('New value for GuidedDraggingTool.guidelineWidth must be a non-negative number.');
if (this._guidelineWidth !== val) {
this._guidelineWidth = val;
if (this.guidelineVcenter) {
(this.guidelineVcenter.elements.first() as go.Shape).strokeWidth = val;
}
if (this.guidelineHcenter) {
(this.guidelineHcenter.elements.first() as go.Shape).strokeWidth = val;
}
if (this.guidelineVleft) {
(this.guidelineVleft.elements.first() as go.Shape).strokeWidth = val;
}
if (this.guidelineVright) {
(this.guidelineVright.elements.first() as go.Shape).strokeWidth = val;
}
if (this.guidelineHbottom) {
(this.guidelineHbottom.elements.first() as go.Shape).strokeWidth = val;
}
if (this.guidelineHtop) {
(this.guidelineHtop.elements.first() as go.Shape).strokeWidth = val;
}
}
}
/**
* Gets or sets the distance around the selected part to search for aligned parts.
*
* The default value is 1000.
* Set this to Infinity if you want to search the entire diagram no matter how far away.
*/
get searchDistance(): number {
return this._searchDistance;
}
set searchDistance(val: number) {
if (typeof val !== 'number' || isNaN(val) || val <= 0) throw new Error('new value for GuidedDraggingTool.searchDistance must be a positive number.');
this._searchDistance = val;
}
/**
* Gets or sets whether snapping to guidelines is enabled.
*
* The default value is true.
*/
get isGuidelineSnapEnabled(): boolean {
return this._isGuidelineSnapEnabled;
}
set isGuidelineSnapEnabled(val: boolean) {
if (typeof val !== 'boolean') throw new Error('new value for GuidedDraggingTool.isGuidelineSnapEnabled must be a boolean.');
this._isGuidelineSnapEnabled = val;
}
/**
* Removes all of the guidelines from the grid.
*/
clearGuidelines(): void {
if (this.guidelineHbottom) this.diagram.remove(this.guidelineHbottom);
if (this.guidelineHcenter) this.diagram.remove(this.guidelineHcenter);
if (this.guidelineHtop) this.diagram.remove(this.guidelineHtop);
if (this.guidelineVleft) this.diagram.remove(this.guidelineVleft);
if (this.guidelineVright) this.diagram.remove(this.guidelineVright);
if (this.guidelineVcenter) this.diagram.remove(this.guidelineVcenter);
}
/**
* Calls the base method and removes the guidelines from the graph.
*/
override doDeactivate(): void {
super.doDeactivate();
// clear any guidelines when dragging is done
this.clearGuidelines();
}
/**
* Shows vertical and horizontal guidelines for the dragged part.
*/
override doDragOver(pt: go.Point, obj: go.GraphObject): void {
// clear all existing guidelines in case either show... method decides to show a guideline
this.clearGuidelines();
// gets the selected part
const draggingParts = this.copiedParts || this.draggedParts;
if (draggingParts === null) return;
const partItr = draggingParts.iterator;
if (partItr.next()) {
const part = partItr.key;
this.showHorizontalMatches(part, this.isGuidelineEnabled, false);
this.showVerticalMatches(part, this.isGuidelineEnabled, false);
}
}
/**
* On a mouse-up, snaps the selected part to the nearest guideline.
* If not snapping, the part remains at its position.
*/
override doDropOnto(pt: go.Point, obj: go.GraphObject): void {
this.clearGuidelines();
// gets the selected (perhaps copied) Part
const draggingParts = this.copiedParts || this.draggedParts;
if (draggingParts === null) return;
const partItr = draggingParts.iterator;
if (partItr.next()) {
const part = partItr.key;
// snaps only when the mouse is released without shift modifier
const e = this.diagram.lastInput;
const snap = this.isGuidelineSnapEnabled && !e.shift;
this.showHorizontalMatches(part, false, snap); // false means don't show guidelines
this.showVerticalMatches(part, false, snap);
}
}
/**
* When nodes are shifted due to being guided upon a drop, make sure all connected link routes are invalidated,
* since the node is likely to have moved a different amount than all its connected links in the regular
* operation of the DraggingTool.
*/
invalidateLinks(node: go.Part): void {
if (node instanceof go.Node) node.invalidateConnectedLinks();
}
/**
* This predicate decides whether or not the given Part should guide the dragged part.
* @param part - a stationary Part to which the dragged part might be aligned
* @param guidedpart - the Part being dragged
*/
protected isGuiding(part: go.Part, guidedpart: go.Part): boolean {
return (
part instanceof go.Part &&
!part.isSelected &&
!(part instanceof go.Link) &&
guidedpart instanceof go.Part &&
part.containingGroup === guidedpart.containingGroup &&
part.layer !== null &&
!part.layer.isTemporary
);
}
/**
* This finds parts that are aligned near the selected part along horizontal lines. It compares the selected
* part to all parts within a rectangle approximately twice the {@link searchDistance} wide.
* The guidelines appear when a part is aligned within a margin-of-error equal to {@link guidelineSnapDistance}.
* @param part
* @param guideline - if true, show guideline
* @param snap - if true, snap the part to where the guideline would be
*/
showHorizontalMatches(part: go.Part, guideline: boolean, snap: boolean): void {
const objBounds = part.locationObject.getDocumentBounds();
const p0 = objBounds.y;
const p1 = objBounds.y + objBounds.height / 2;
const p2 = objBounds.y + objBounds.height;
const marginOfError = this.guidelineSnapDistance;
let distance = this.searchDistance;
if (distance === Infinity) distance = this.diagram.documentBounds.width;
// compares with parts within narrow vertical area
const area = objBounds.copy();
area.inflate(distance, marginOfError + 1);
const otherObjs = this.diagram.findObjectsIn(
area,
(obj) => obj.part as go.Part,
(p) => this.isGuiding(p as go.Part, part),
true
) as go.Set<go.Part>;
let bestDiff: number = marginOfError;
let bestObj: any = null; // TS 2.6 won't let this be go.Part | null
let bestSpot: go.Spot = go.Spot.Default;
let bestOtherSpot: go.Spot = go.Spot.Default;
// horizontal line -- comparing y-values
otherObjs.each((other) => {
if (other === part) return; // ignore itself
const otherBounds = other.locationObject.getDocumentBounds();
const q0 = otherBounds.y;
const q1 = otherBounds.y + otherBounds.height / 2;
const q2 = otherBounds.y + otherBounds.height;
// compare center with center of OTHER part
if (this.guidelineHcenter && Math.abs(p1 - q1) < bestDiff) {
bestDiff = Math.abs(p1 - q1);
bestObj = other;
bestSpot = go.Spot.Center;
bestOtherSpot = go.Spot.Center;
}
// compare top side with top and bottom sides of OTHER part
if (this.guidelineHtop && Math.abs(p0 - q0) < bestDiff) {
bestDiff = Math.abs(p0 - q0);
bestObj = other;
bestSpot = go.Spot.Top;
bestOtherSpot = go.Spot.Top;
} else if (this.guidelineHtop && Math.abs(p0 - q2) < bestDiff) {
bestDiff = Math.abs(p0 - q2);
bestObj = other;
bestSpot = go.Spot.Top;
bestOtherSpot = go.Spot.Bottom;
}
// compare bottom side with top and bottom sides of OTHER part
if (this.guidelineHbottom && Math.abs(p2 - q0) < bestDiff) {
bestDiff = Math.abs(p2 - q0);
bestObj = other;
bestSpot = go.Spot.Bottom;
bestOtherSpot = go.Spot.Top;
} else if (this.guidelineHbottom && Math.abs(p2 - q2) < bestDiff) {
bestDiff = Math.abs(p2 - q2);
bestObj = other;
bestSpot = go.Spot.Bottom;
bestOtherSpot = go.Spot.Bottom;
}
});
if (bestObj !== null) {
const offsetX = objBounds.x - part.actualBounds.x;
const offsetY = objBounds.y - part.actualBounds.y;
const bestBounds = bestObj.locationObject.getDocumentBounds();
// line extends from x0 to x2
const x0 = Math.min(objBounds.x, bestBounds.x) - 10;
const x2 = Math.max(objBounds.x + objBounds.width, bestBounds.x + bestBounds.width) + 10;
// find bestObj's desired Y
const bestPoint = new go.Point().setRectSpot(bestBounds, bestOtherSpot);
if (bestSpot === go.Spot.Center) {
if (snap) {
// call Part.move in order to automatically move member Parts of Groups
part.move(
new go.Point(objBounds.x - offsetX, bestPoint.y - objBounds.height / 2 - offsetY)
);
this.invalidateLinks(part);
}
if (guideline) {
this.guidelineHcenter.position = new go.Point(x0, bestPoint.y);
this.guidelineHcenter.elt(0).width = x2 - x0;
this.diagram.add(this.guidelineHcenter);
}
} else if (bestSpot === go.Spot.Top) {
if (snap) {
part.move(new go.Point(objBounds.x - offsetX, bestPoint.y - offsetY));
this.invalidateLinks(part);
}
if (guideline) {
this.guidelineHtop.position = new go.Point(x0, bestPoint.y);
this.guidelineHtop.elt(0).width = x2 - x0;
this.diagram.add(this.guidelineHtop);
}
} else if (bestSpot === go.Spot.Bottom) {
if (snap) {
part.move(new go.Point(objBounds.x - offsetX, bestPoint.y - objBounds.height - offsetY));
this.invalidateLinks(part);
}
if (guideline) {
this.guidelineHbottom.position = new go.Point(x0, bestPoint.y);
this.guidelineHbottom.elt(0).width = x2 - x0;
this.diagram.add(this.guidelineHbottom);
}
}
}
}
/**
* This finds parts that are aligned near the selected part along vertical lines. It compares the selected
* part to all parts within a rectangle approximately twice the {@link searchDistance} tall.
* The guidelines appear when a part is aligned within a margin-of-error equal to {@link guidelineSnapDistance}.
* @param part
* @param guideline - if true, show guideline
* @param snap - if true, don't show guidelines but just snap the part to where the guideline would be
*/
showVerticalMatches(part: go.Part, guideline: boolean, snap: boolean): void {
const objBounds = part.locationObject.getDocumentBounds();
const p0 = objBounds.x;
const p1 = objBounds.x + objBounds.width / 2;
const p2 = objBounds.x + objBounds.width;
const marginOfError = this.guidelineSnapDistance;
let distance = this.searchDistance;
if (distance === Infinity) distance = this.diagram.documentBounds.height;
// compares with parts within narrow vertical area
const area = objBounds.copy();
area.inflate(marginOfError + 1, distance);
const otherObjs = this.diagram.findObjectsIn(
area,
(obj) => obj.part as go.Part,
(p) => this.isGuiding(p as go.Part, part),
true
) as go.Set<go.Part>;
let bestDiff: number = marginOfError;
let bestObj: any = null; // TS 2.6 won't let this be go.Part | null
let bestSpot: go.Spot = go.Spot.Default;
let bestOtherSpot: go.Spot = go.Spot.Default;
// vertical line -- comparing x-values
otherObjs.each((other) => {
if (other === part) return; // ignore itself
const otherBounds = other.locationObject.getDocumentBounds();
const q0 = otherBounds.x;
const q1 = otherBounds.x + otherBounds.width / 2;
const q2 = otherBounds.x + otherBounds.width;
// compare center with center of OTHER part
if (this.guidelineVcenter && Math.abs(p1 - q1) < bestDiff) {
bestDiff = Math.abs(p1 - q1);
bestObj = other;
bestSpot = go.Spot.Center;
bestOtherSpot = go.Spot.Center;
}
// compare left side with left and right sides of OTHER part
if (this.guidelineVleft && Math.abs(p0 - q0) < bestDiff) {
bestDiff = Math.abs(p0 - q0);
bestObj = other;
bestSpot = go.Spot.Left;
bestOtherSpot = go.Spot.Left;
} else if (this.guidelineVleft && Math.abs(p0 - q2) < bestDiff) {
bestDiff = Math.abs(p0 - q2);
bestObj = other;
bestSpot = go.Spot.Left;
bestOtherSpot = go.Spot.Right;
}
// compare right side with left and right sides of OTHER part
if (this.guidelineVright && Math.abs(p2 - q0) < bestDiff) {
bestDiff = Math.abs(p2 - q0);
bestObj = other;
bestSpot = go.Spot.Right;
bestOtherSpot = go.Spot.Left;
} else if (this.guidelineVright && Math.abs(p2 - q2) < bestDiff) {
bestDiff = Math.abs(p2 - q2);
bestObj = other;
bestSpot = go.Spot.Right;
bestOtherSpot = go.Spot.Right;
}
});
if (bestObj !== null) {
const offsetX = objBounds.x - part.actualBounds.x;
const offsetY = objBounds.y - part.actualBounds.y;
const bestBounds = bestObj.locationObject.getDocumentBounds();
// line extends from y0 to y2
const y0 = Math.min(objBounds.y, bestBounds.y) - 10;
const y2 = Math.max(objBounds.y + objBounds.height, bestBounds.y + bestBounds.height) + 10;
// find bestObj's desired X
const bestPoint = new go.Point().setRectSpot(bestBounds, bestOtherSpot);
if (bestSpot === go.Spot.Center) {
if (snap) {
// call Part.move in order to automatically move member Parts of Groups
part.move(
new go.Point(bestPoint.x - objBounds.width / 2 - offsetX, objBounds.y - offsetY)
);
this.invalidateLinks(part);
}
if (guideline) {
this.guidelineVcenter.position = new go.Point(bestPoint.x, y0);
this.guidelineVcenter.elt(0).height = y2 - y0;
this.diagram.add(this.guidelineVcenter);
}
} else if (bestSpot === go.Spot.Left) {
if (snap) {
part.move(new go.Point(bestPoint.x - offsetX, objBounds.y - offsetY));
this.invalidateLinks(part);
}
if (guideline) {
this.guidelineVleft.position = new go.Point(bestPoint.x, y0);
this.guidelineVleft.elt(0).height = y2 - y0;
this.diagram.add(this.guidelineVleft);
}
} else if (bestSpot === go.Spot.Right) {
if (snap) {
part.move(new go.Point(bestPoint.x - objBounds.width - offsetX, objBounds.y - offsetY));
this.invalidateLinks(part);
}
if (guideline) {
this.guidelineVright.position = new go.Point(bestPoint.x, y0);
this.guidelineVright.elt(0).height = y2 - y0;
this.diagram.add(this.guidelineVright);
}
}
}
}
}
/*
* Copyright (C) 1998-2024 by Northwoods Software Corporation. All Rights Reserved.
*/
/*
* This is an extension and not part of the main GoJS library.
* Note that the API for this class may change with any version, even point releases.
* If you intend to use an extension in production, you should copy the code to your own source directory.
* Extensions can be found in the GoJS kit under the extensions or extensionsJSM folders.
* See the Extensions intro page (https://gojs.net/latest/intro/extensions.html) for more information.
*/
import * as go from 'gojs';
/**
* The LinkLabelDraggingTool class lets the user move a label on a {@link go.Link}.
*
* This tool only works when the Link has a label
* that is positioned at the {@link go.Link.midPoint} plus some offset.
* It does not work for labels that have a particular {@link go.GraphObject.segmentIndex}.
*
* If you want to experiment with this extension, try the <a href="../../samples/LinkLabelDragging.html">Link Label Dragging</a> sample.
* @category Tool Extension
*/
export class LinkLabelDraggingTool extends go.Tool {
/**
* The label being dragged.
*/
label: go.GraphObject | null;
private _offset: go.Point; // of the mouse relative to the center of the label object
private _originalOffset: go.Point | null;
/**
* Constructs a LinkLabelDraggingTool and sets the name for the tool.
*/
constructor(init?: Partial<LinkLabelDraggingTool>) {
super();
this.name = 'LinkLabelDragging';
this.label = null;
this._offset = new go.Point();
this._originalOffset = null;
if (init) Object.assign(this, init);
}
/**
* From the GraphObject at the mouse point, search up the visual tree until we get to
* an object that is a label of a Link.
* @returns This returns null if no such label is at the mouse down point.
*/
findLabel(): go.GraphObject | null {
const diagram = this.diagram;
const e = diagram.lastInput;
let elt = diagram.findObjectAt(e.documentPoint, null, null);
if (elt === null || !(elt.part instanceof go.Link)) return null;
while (elt !== null && elt.panel !== elt.part) {
elt = elt.panel;
}
// If it's at an arrowhead segment index, don't consider it a label:
if (elt !== null && (elt.segmentIndex === 0 || elt.segmentIndex === -1)) return null;
return elt;
}
/**
* This tool can only start if the mouse has moved enough so that it is not a click,
* and if the mouse down point is on a GraphObject "label" in a Link Panel,
* as determined by {@link findLabel}.
*/
override canStart(): boolean {
if (!super.canStart()) return false;
const diagram = this.diagram;
// require left button & that it has moved far enough away from the mouse down point, so it isn't a click
const e = diagram.lastInput;
if (!e.left) return false;
if (!this.isBeyondDragSize()) return false;
return this.findLabel() !== null;
}
/**
* Start a transaction, call {@link findLabel} and remember it as the "label" property,
* and remember the original value for the label's {@link go.GraphObject.segmentOffset} property.
*/
override doActivate(): void {
this.startTransaction('Shifted Label');
this.label = this.findLabel();
if (this.label !== null) {
// compute the offset of the mouse-down point relative to the center of the label
this._offset = this.diagram.firstInput.documentPoint
.copy()
.subtract(this.label.getDocumentPoint(go.Spot.Center));
this._originalOffset = this.label.segmentOffset.copy();
}
super.doActivate();
}
/**
* Stop any ongoing transaction.
*/
override doDeactivate(): void {
super.doDeactivate();
this.stopTransaction();
}
/**
* Clear any reference to a label element.
*/
override doStop(): void {
this.label = null;
super.doStop();
}
/**
* Restore the label's original value for {@link go.GraphObject.segmentOffset}.
*/
override doCancel(): void {
if (this.label !== null && this._originalOffset !== null) {
this.label.segmentOffset = this._originalOffset;
}
super.doCancel();
}
/**
* During the drag, call {@link updateSegmentOffset} in order to set
* the {@link go.GraphObject.segmentOffset} of the label.
*/
override doMouseMove(): void {
if (!this.isActive) return;
this.updateSegmentOffset();
}
/**
* At the end of the drag, update the segment offset of the label and finish the tool,
* completing a transaction.
*/
override doMouseUp(): void {
if (!this.isActive) return;
this.updateSegmentOffset();
this.transactionResult = 'Shifted Label';
this.stopTool();
}
/**
* Save the label's {@link go.GraphObject.segmentOffset} as a rotated offset from the midpoint of the
* Link that the label is in.
*/
updateSegmentOffset(): void {
const lab = this.label;
if (lab === null) return;
const link = lab.part;
if (!(link instanceof go.Link)) return;
const last = this.diagram.lastInput.documentPoint;
const idx = lab.segmentIndex;
const numpts = link.pointsCount;
if (isNaN(idx) && link.path) {
// handle fractions along the whole path
const labpt = link.path.getDocumentPoint(
link.geometry.getPointAlongPath(lab.segmentFraction)
);
const angle = link.geometry.getAngleAlongPath(lab.segmentFraction);
const p = new go.Point(last.x - this._offset.x - labpt.x, last.y - this._offset.y - labpt.y);
lab.segmentOffset = p.rotate(-angle);
} else if (idx < -numpts || idx >= numpts) {
// if the label is a "mid" label, assume it is positioned differently from a label at a particular segment
const mid = link.midPoint;
// need to rotate this point to account for the angle of the link segment at the mid-point
const p = new go.Point(last.x - this._offset.x - mid.x, last.y - this._offset.y - mid.y);
lab.segmentOffset = p.rotate(-link.midAngle);
} else {
// handle the label point being on a partiular segment with a given fraction
const frac = lab.segmentFraction;
let a: go.Point;
let b: go.Point;
if (idx >= 0) {
// indexing forwards
a = link.getPoint(idx);
b = idx < numpts - 1 ? link.getPoint(idx + 1) : a;
} else {
// or backwards if segmentIndex is negative
const i = numpts + idx;
a = link.getPoint(i);
b = i > 0 ? link.getPoint(i - 1) : a;
}
const labx = a.x + (b.x - a.x) * frac;
const laby = a.y + (b.y - a.y) * frac;
const p = new go.Point(last.x - this._offset.x - labx, last.y - this._offset.y - laby);
const segangle = idx >= 0 ? a.directionPoint(b) : b.directionPoint(a);
lab.segmentOffset = p.rotate(-segangle);
}
}
}
/*
* Copyright (C) 1998-2024 by Northwoods Software Corporation. All Rights Reserved.
*/
/*
* This is an extension and not part of the main GoJS library.
* Note that the API for this class may change with any version, even point releases.
* If you intend to use an extension in production, you should copy the code to your own source directory.
* Extensions can be found in the GoJS kit under the extensions or extensionsJSM folders.
* See the Extensions intro page (https://gojs.net/latest/intro/extensions.html) for more information.
*/
import * as go from 'gojs';
/**
* The NodeLabelDraggingTool class lets the user move a label on a Node.
*
* This tool only works when the Node has a label (any GraphObject) marked with
* `{ _isNodeLabel: true }` that is positioned in a Spot Panel.
* It works by modifying that label's {@link go.GraphObject.alignment} property to have an
* offset from the center of the panel.
*
* If you want to experiment with this extension, try the <a href="../../samples/NodeLabelDragging.html">Node Label Dragging</a> sample.
* @category Tool Extension
*/
export class NodeLabelDraggingTool extends go.Tool {
/**
* The label being dragged.
*/
label: go.GraphObject | null;
private _offset: go.Point; // of the mouse relative to the center of the label object
private _originalAlignment: go.Spot;
private _originalCenter: go.Point;
/**
* Constructs a NodeLabelDraggingTool and sets the name for the tool.
*/
constructor(init?: Partial<NodeLabelDraggingTool>) {
super();
this.name = 'NodeLabelDragging';
this.label = null;
this._offset = new go.Point();
this._originalAlignment = go.Spot.Default;
this._originalCenter = new go.Point();
if (init) Object.assign(this, init);
}
/**
* From the GraphObject at the mouse point, search up the visual tree until we get to
* an object that has the "_isNodeLabel" property set to true, that is in a Spot Panel,
* and that is not the first element of that Panel (i.e. not the main element of the panel).
* @returns This returns null if no such label is at the mouse down point.
*/
findLabel(): go.GraphObject | null {
const diagram = this.diagram;
const e = diagram.firstInput;
let elt = diagram.findObjectAt(e.documentPoint, null, null);
if (elt === null || !(elt.part instanceof go.Node)) return null;
while (elt.panel !== null) {
if ((elt as any)['_isNodeLabel'] &&
elt.panel.type === go.Panel.Spot &&
elt.panel.findMainElement() !== elt) return elt;
elt = elt.panel;
}
return null;
}
/**
* This tool can only start if the mouse has moved enough so that it is not a click,
* and if the mouse down point is on a GraphObject "label" in a Spot Panel,
* as determined by findLabel().
*/
override canStart(): boolean {
if (!super.canStart()) return false;
const diagram = this.diagram;
// require left button & that it has moved far enough away from the mouse down point, so it isn't a click
const e = diagram.lastInput;
if (!e.left) return false;
if (!this.isBeyondDragSize()) return false;
return this.findLabel() !== null;
}
/**
* Start a transaction, call {@link findLabel} and remember it as the "label" property,
* and remember the original value for the label's {@link go.GraphObject.alignment} property.
*/
override doActivate(): void {
this.startTransaction('Shifted Label');
this.label = this.findLabel();
if (this.label !== null) {
// compute the offset of the mouse-down point relative to the center of the label
this._offset = this.diagram.firstInput.documentPoint
.copy()
.subtract(this.label.getDocumentPoint(go.Spot.Center));
this._originalAlignment = this.label.alignment.copy();
const panel = this.label.panel;
if (panel !== null) {
const main = panel.findMainElement();
if (main !== null) this._originalCenter = main.getDocumentPoint(go.Spot.Center);
}
}
super.doActivate();
}
/**
* Stop any ongoing transaction.
*/
override doDeactivate(): void {
super.doDeactivate();
this.stopTransaction();
}
/**
* Clear any reference to a label element.
*/
override doStop(): void {
this.label = null;
super.doStop();
}
/**
* Restore the label's original value for GraphObject.alignment.
*/
override doCancel(): void {
if (this.label !== null) {
this.label.alignment = this._originalAlignment;
}
super.doCancel();
}
/**
* During the drag, call updateAlignment in order to set the {@link go.GraphObject.alignment} of the label.
*/
override doMouseMove(): void {
if (!this.isActive) return;
this.updateAlignment();
}
/**
* At the end of the drag, update the alignment of the label and finish the tool,
* completing a transaction.
*/
override doMouseUp(): void {
if (!this.isActive) return;
this.updateAlignment();
this.transactionResult = 'Shifted Label';
this.stopTool();
}
/**
* Save the label's {@link go.GraphObject.alignment} as an absolute offset from the center of the Spot Panel
* that the label is in.
*/
updateAlignment(): void {
if (this.label === null) return;
const last = this.diagram.lastInput.documentPoint;
const cntr = this._originalCenter;
this.label.alignment = new go.Spot(
0.5,
0.5,
last.x - this._offset.x - cntr.x,
last.y - this._offset.y - cntr.y
);
}
}
/*
* Copyright (C) 1998-2024 by Northwoods Software Corporation. All Rights Reserved.
*/
/*
* This is an extension and not part of the main GoJS library.
* Note that the API for this class may change with any version, even point releases.
* If you intend to use an extension in production, you should copy the code to your own source directory.
* Extensions can be found in the GoJS kit under the extensions or extensionsJSM folders.
* See the Extensions intro page (https://gojs.net/latest/intro/extensions.html) for more information.
*/
import * as go from 'gojs';
/**
* The PortShiftingTool class lets a user move a port on a {@link go.Node}.
*
* This tool only works when the Node has a port (any GraphObject) marked with
* a non-null and non-empty portId that is positioned in a Spot Panel,
* and the user holds down the Shift key.
* It works by modifying that port's {@link go.GraphObject.alignment} property.
*
* If you want to experiment with this extension, try the <a href="../../samples/PortShifting.html">Port Shifting</a> sample.
* @category Tool Extension
*/
export class PortShiftingTool extends go.Tool {
/**
* The port being shifted.
*/
port: go.GraphObject | null;
private _originalAlignment: go.Spot;
/**
* Constructs a PortShiftingTool and sets the name for the tool.
*/
constructor(init?: Partial<PortShiftingTool>) {
super();
this.name = 'PortShifting';
this.port = null;
this._originalAlignment = go.Spot.Default;
if (init) Object.assign(this, init);
}
/**
* This tool can only start if the mouse has moved enough so that it is not a click,
* and if the mouse down point is on a GraphObject "port" in a Spot Panel,
* as determined by {@link findPort}.
*/
override canStart(): boolean {
const diagram = this.diagram;
if (!super.canStart()) return false;
// require left button & that it has moved far enough away from the mouse down point, so it isn't a click
const e = diagram.lastInput;
if (!e.left || !e.shift) return false;
if (!this.isBeyondDragSize()) return false;
return this.findPort() !== null;
}
/**
* From the {@link go.GraphObject} at the mouse point, search up the visual tree until we get to
* an object that has the {@link go.GraphObject.portId} property set to a non-empty string, that is in a Spot Panel,
* and that is not the main element of the panel (typically the first element).
* @returns This returns null if no such port is at the mouse down point.
*/
findPort(): go.GraphObject | null {
const diagram = this.diagram;
const e = diagram.firstInput;
let elt = diagram.findObjectAt(e.documentPoint, null, null);
if (elt === null || !(elt.part instanceof go.Node)) return null;
while (elt !== null && elt.panel !== null) {
if (elt.panel.type === go.Panel.Spot &&
elt.panel.findMainElement() !== elt &&
elt.portId !== null &&
elt.portId !== '') return elt;
elt = elt.panel;
}
return null;
}
/**
* Start a transaction, call {@link findPort} and remember it as the "port" property,
* and remember the original value for the port's {@link go.GraphObject.alignment} property.
*/
override doActivate(): void {
this.startTransaction('Shifted Label');
this.port = this.findPort();
if (this.port !== null) {
this._originalAlignment = this.port.alignment.copy();
}
super.doActivate();
}
/**
* Stop any ongoing transaction.
*/
override doDeactivate(): void {
super.doDeactivate();
this.stopTransaction();
}
/**
* Clear any reference to a port element.
*/
override doStop(): void {
this.port = null;
super.doStop();
}
/**
* Restore the port's original value for GraphObject.alignment.
*/
override doCancel(): void {
if (this.port !== null) {
this.port.alignment = this._originalAlignment;
}
super.doCancel();
}
/**
* During the drag, call {@link updateAlignment} in order to set the {@link go.GraphObject.alignment} of the port.
*/
override doMouseMove(): void {
if (!this.isActive) return;
this.updateAlignment();
}
/**
* At the end of the drag, update the alignment of the port and finish the tool,
* completing a transaction.
*/
override doMouseUp(): void {
if (!this.isActive) return;
this.updateAlignment();
this.transactionResult = 'Shifted Label';
this.stopTool();
}
/**
* Save the port's {@link go.GraphObject.alignment} as a fractional Spot in the Spot Panel
* that the port is in. Thus if the main element changes size, the relative positions
* of the ports will be maintained. But that does assume that the port must remain
* inside the main element -- it cannot wander away from the node.
* This does not modify the port's {@link go.GraphObject.alignmentFocus} property.
*/
updateAlignment(): void {
if (this.port === null || this.port.panel === null) return;
const last = this.diagram.lastInput.documentPoint;
const main = this.port.panel.findMainElement();
if (main === null) return;
const tl = main.getDocumentPoint(go.Spot.TopLeft);
const br = main.getDocumentPoint(go.Spot.BottomRight);
const x = Math.max(0, Math.min((last.x - tl.x) / (br.x - tl.x), 1));
const y = Math.max(0, Math.min((last.y - tl.y) / (br.y - tl.y), 1));
this.port.alignment = new go.Spot(x, y);
}
}
/*
* Copyright (C) 1998-2024 by Northwoods Software Corporation. All Rights Reserved.
*/
/*
* This is an extension and not part of the main GoJS library.
* Note that the API for this class may change with any version, even point releases.
* If you intend to use an extension in production, you should copy the code to your own source directory.
* Extensions can be found in the GoJS kit under the extensions or extensionsJSM folders.
* See the Extensions intro page (https://gojs.net/latest/intro/extensions.html) for more information.
*/
import * as go from 'gojs';
/**
* The ResizeMultipleTool class lets the user resize multiple objects at once.
*
* If you want to experiment with this extension, try the <a href="../../samples/ResizeMultiple.html">Resize Multiple</a> sample.
* @category Tool Extension
*/
export class ResizeMultipleTool extends go.ResizingTool {
/**
* Constructs a ResizeMultipleTool and sets the name for the tool.
*/
constructor(init?: Partial<ResizeMultipleTool>) {
super();
this.name = 'ResizeMultiple';
if (init) Object.assign(this, init);
}
/**
* Overrides {@link go.ResizingTool.resize} to resize all selected objects to the same size.
* @param newr - the intended new rectangular bounds for each Part's {@link go.Part.resizeObject}.
*/
override resize(newr: go.Rect): void {
const diagram = this.diagram;
diagram.selection.each((part) => {
if (part instanceof go.Link) return; // only Nodes and simple Parts
const obj = part.resizeObject;
// calculate new location
const pos = part.position.copy();
const angle = obj.getDocumentAngle();
const sc = obj.getDocumentScale();
const radAngle = (Math.PI * angle) / 180;
const angleCos = Math.cos(radAngle);
const angleSin = Math.sin(radAngle);
const deltaWidth = newr.width - obj.naturalBounds.width;
const deltaHeight = newr.height - obj.naturalBounds.height;
const angleBottom = angle > 0 && angle < 180 ? 1 : 0;
const angleLeft = angle > 90 && angle < 270 ? 1 : 0;
const angleTop = angle > 180 && angle < 360 ? 1 : 0;
pos.x +=
sc *
((newr.x + deltaWidth * angleLeft) * angleCos -
(newr.y + deltaHeight * angleBottom) * angleSin);
pos.y +=
sc *
((newr.x + deltaWidth * angleTop) * angleSin +
(newr.y + deltaHeight * angleLeft) * angleCos);
obj.desiredSize = newr.size;
part.move(pos);
});
}
}
<template>
<div class="common-layout">
<div class="layout-container">
<div id="PaletteDiv" class="layout-aside">
<div class="svg_class" draggable="true" @dragstart="dragstart">
<img src="./pid_node/渣池.svg">
</div>
<div style="background-color: aqua; width: 100px; height: 100px;" draggable="true" @dragstart="dragstart">html元素</div>
</div>
<div id="diagramDiv" class="layout-main" @dragover="event => event.preventDefault()"
@dragenter="event => event.preventDefault()" @drop="drop"></div>
</div>
</div>
<div>
<button @click="exportData">导出数据</button>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import go from 'gojs';
import { PortShiftingTool } from './extensions/PortShiftingTool';
import { ResizeMultipleTool } from './extensions/ResizeMultipleTool';
import { LinkLabelDraggingTool } from './extensions/LinkLabelDraggingTools';
import { NodeLabelDraggingTool } from './extensions/NodeLabelDraggingTool';
import { GuidedDraggingTool } from './extensions/GuidedDraggingTool';
const $ = go.GraphObject.make;
var myDiagram: any;
function initDiagram() {
myDiagram = $(go.Diagram, "diagramDiv", {
"undoManager.isEnabled": true,
"toolManager.mouseWheelBehavior": go.WheelMode.Zoom,
// contentAlignment: go.Spot.Center, // 元素位置移动后始终处于在画布正中间
resizingTool: new ResizeMultipleTool(), // 自定义ResizeMultipleTool()方法来设置元素大小的缩放
draggingTool: new GuidedDraggingTool(), // 使用节点对齐辅助
// 设置辅助对齐的线条的样式
"draggingTool.horizontalGuidelineColor": "blue", // 水平两侧的辅助线条为蓝色
"draggingTool.verticalGuidelineColor": "blue", // 垂直两侧的辅助线条为蓝色
"draggingTool.centerGuidelineColor": "green", // 节点中心的水平和垂直对齐的辅助线条为绿色
"draggingTool.guidelineWidth": 1, // 设置辅助对齐的线条的粗细
});
myDiagram.toolManager.mouseMoveTools.insertAt(0, new PortShiftingTool()); // 设置端口移动
myDiagram.toolManager.mouseMoveTools.insertAt(0, new LinkLabelDraggingTool()); // 设置链接上的文本可以移动
myDiagram.toolManager.mouseMoveTools.insertAt(0, new NodeLabelDraggingTool()); // 设置节点上的文本可以移动
myDiagram.nodeTemplate =
$(go.Node, "Spot",
{
resizable: true
},
new go.Binding("location", "loc"),
new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify), // 进行元素位置信息的绑定
$(go.Shape, "RoundedRectangle",
{
fill: "white",
strokeWidth: 0
},
new go.Binding("fill", "color"),
),
$(go.TextBlock,
{
margin: 10,
textAlign: 'center',
font: 'bold 14px Segoe UI,sans-serif',
stroke: '#484848',
editable: true,
_isNodeLabel: true,
cursor: "move"
},
new go.Binding('text', 'key').makeTwoWay(),
),
$(go.Shape, "Rectangle",
{
width: 6,
height: 6,
portId: "Top",
fromSpot: go.Spot.Top, // 从端口顶部发出连接
toSpot: go.Spot.Top, // 从端口顶部接收连接
fromLinkable: true,
toLinkable: true,
cursor: 'pointer',
alignment: new go.Spot(0.5, 0)
}
),
$(go.Shape, "Rectangle",
{
width: 6,
height: 6,
portId: "Left",
fromSpot: go.Spot.Left,
toSpot: go.Spot.Left,
fromLinkable: true,
toLinkable: true,
cursor: 'pointer',
alignment: new go.Spot(0, 0.5)
}
),
$(go.Shape, "Rectangle",
{
width: 6,
height: 6,
portId: "Right",
fromSpot: go.Spot.Right,
toSpot: go.Spot.Right,
fromLinkable: true,
toLinkable: true,
cursor: 'pointer',
alignment: new go.Spot(1, 0.5)
}
),
$(go.Shape, "Rectangle",
{
width: 6,
height: 6,
portId: "Bottom",
fromSpot: go.Spot.Bottom,
toSpot: go.Spot.Bottom,
fromLinkable: true,
toLinkable: true,
cursor: 'pointer',
alignment: new go.Spot(0.5, 1)
}
),
);
myDiagram.nodeTemplateMap.add('zhaChi',
$(go.Node, "Spot",
{
resizable: true
},
new go.Binding("location", "loc"),
new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify), // 进行元素位置信息的绑定
$(go.Shape, "RoundedRectangle",
{
geometry: go.Geometry.parse("XFM88 77.8 0 77.8 0 53.8 88 53.8 136.6 0 181.4 0 181.4 35.3 157.5 35.3 157.5 24.5 136.6 24.5z XM 86.8 70.1 L 141.7 10.2 XM 82.8 66.1 L 137.1 6.4 XM142 8.8B 0 360 139 8.8 3 3 XM87 68.8B 0 360 84 68.8 3 3"),
stroke: "black",
fill: "white",
strokeWidth: 1.5
},
),
$(go.TextBlock,
{
margin: 10,
textAlign: 'center',
font: 'bold 14px Segoe UI,sans-serif',
stroke: '#484848',
editable: true,
_isNodeLabel: true,
cursor: "move"
},
new go.Binding('text', 'key').makeTwoWay(),
),
$(go.Shape, "Rectangle",
{
width: 6,
height: 6,
portId: "Bottom",
fromSpot: go.Spot.Bottom,
toSpot: go.Spot.Bottom,
fromLinkable: true,
toLinkable: true,
cursor: 'pointer',
alignment: new go.Spot(0.5, 1)
}
),
)
);
myDiagram.linkTemplate =
$(go.Link,
{
routing:go.Routing.AvoidsNodes,
curve: go.Curve.JumpGap,
corner: 5,
adjusting: go.LinkAdjusting.Stretch,
reshapable: true // 设置连接线的形态是否可以被修改
},
$(go.Shape, // 链接线的样式
{
strokeWidth: 1.5
}
),
$(go.Shape, // 箭头的样式
{
toArrow: "standard",
stroke: null
}
),
$(go.Panel, "Auto",
{ cursor: "move" }, // 用户可以使用此链接标签执行某些操作的视觉提示
$(go.Shape, // 设置链接中的标签样式
{
fill: "lightgray",
stroke: null
}
),
$(go.TextBlock, "transition", // 设置链接中标签的文本样式
{
textAlign: "center",
font: "10pt helvetica, arial, sans-serif",
stroke: "black",
margin: 4,
editable: true // 设置标签文本是否可编辑
},
new go.Binding("text", "text").makeTwoWay()), // 文本数据双向绑定
new go.Binding("segmentOffset", "segmentOffset", go.Point.parse).makeTwoWay(go.Point.stringify)
)
);
const nodeDataArray = [
{ key: "add1", color: "lightyellow", loc: new go.Point(-150, 200) },
{ key: "add2", color: "lightblue", loc: new go.Point(100, 50), category: "zhaChi" },
];
const linkDataArray = [
{ from: "add1", fromPort: "Top", to: "add2", toPort: "Bottom", text: "1->2" },
];
myDiagram.model =
$(go.GraphLinksModel,
{
linkFromPortIdProperty: "fromPort",
linkToPortIdProperty: "toPort",
nodeDataArray: nodeDataArray,
linkDataArray: linkDataArray
}
);
}
function exportData() {
if (myDiagram) {
console.log(myDiagram.model.toJson());
}
}
const dragStartOffsetX = ref()
const dragStartOffsetY = ref()
// 获取拖动开始时的偏移量
function dragstart(event: any){
const target = event.target;
dragStartOffsetX.value = event.offsetX - target.clientWidth / 2;
dragStartOffsetY.value = event.offsetY - target.clientHeight / 2;
}
// html元素拖动到画布中
function drop(event: any) {
event.preventDefault(); // 不要执行浏览器的默认操作,执行下面自定义的函数方法
const target = event.target; // 指向事件触发的原始元素
// 获取像素比率
const pixelRatio = myDiagram.computePixelRatio();
if (!(target instanceof HTMLCanvasElement)) return;
// 获取目标元素的边界框
const bbox = target.getBoundingClientRect();
let bbw = bbox.width;
if (bbw === 0) bbw = 0.001;
let bbh = bbox.height;
if (bbh === 0) bbh = 0.001;
console.log(bbox)
// 计算鼠标在画布上的位置
const mx = event.clientX - bbox.left * (target.width / pixelRatio / bbw);
const my = event.clientY - bbox.top * (target.height / pixelRatio / bbh);
const point = myDiagram.transformViewToDoc(new go.Point(mx - dragStartOffsetX.value, my - dragStartOffsetY.value));
// console.log(mx)
// console.log(my)
// console.log(point)
// 开始一个新的事务
myDiagram.startTransaction('new node');
const newData = {
key: 'html元素',
color: 'aqua',
loc: new go.Point(point.x, point.y),
// category: "" // 使用标准模板绘制节点
category: "zhaChi" // 使用zhaChi的模板绘制节点
};
myDiagram.model.addNodeData(newData);
myDiagram.commitTransaction('new node');
}
onMounted(() => {
initDiagram()
});
</script>
<style>
.common-layout {
display: flex;
justify-content: space-between;
}
.layout-container {
display: flex;
width: 100%;
}
.layout-aside {
width: 10%;
height: 900px;
background-color: rgb(216, 212, 212);
}
.layout-main {
width: 90%;
height: 900px;
background-color: #DAE4E4;
}
.svg_class {
width: 100px;
height: 100px;
background-color: white;
/* border: 1px solid black; */
display: flex;
justify-content: center;
align-items: center;
}
</style>
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 190 90" style="enable-background:new 0 0 190 90;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;stroke:#333333;stroke-width:2;}
.st1{fill:none;stroke:#333333;stroke-width:2;}
</style>
<g id="页面-1">
<g id="渣池">
<g id="编组" transform="translate(4.000000, 6.000000)">
<polygon id="路径" class="st0" points="88,77.8 0,77.8 0,53.8 88,53.8 136.6,0 181.4,0 181.4,35.3 157.5,35.3 157.5,24.5
136.6,24.5 "/>
<circle id="椭圆形" class="st1" cx="139" cy="8.8" r="3"/>
<circle id="椭圆形备份" class="st1" cx="84" cy="68.8" r="3"/>
<line id="路径-24" class="st1" x1="86.8" y1="70.1" x2="141.7" y2="10.2"/>
<line id="路径-24备份" class="st1" x1="82.8" y1="66.1" x2="137.1" y2="6.4"/>
</g>
</g>
</g>
</svg>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment