说明
效果
代码
vue
<script setup>
import { ref, onMounted } from 'vue';
import {
mxEvent,
mxGraph,
mxRubberband,
mxConstants,
mxUtils,
mxPoint,
} from 'thgraph';
onMounted(() => {
main();
});
function main() {
const container = document.getElementById('graphContainer');
// Disables the built-in context menu
mxEvent.disableContextMenu(container);
// Creates the graph inside the given container
var graph = new mxGraph(container);
// Sets the base style for all vertices
var style = graph.getStylesheet().getDefaultVertexStyle();
style[mxConstants.STYLE_ROUNDED] = true;
style[mxConstants.STYLE_FILLCOLOR] = '#ffffff';
style[mxConstants.STYLE_STROKECOLOR] = '#000000';
style[mxConstants.STYLE_STROKEWIDTH] = '2';
style[mxConstants.STYLE_FONTCOLOR] = '#000000';
style[mxConstants.STYLE_FONTSIZE] = '12';
style[mxConstants.STYLE_FONTSTYLE] = 1;
graph.getStylesheet().putDefaultVertexStyle(style);
// Removes folding icon for relative children
graph.isCellFoldable = function (cell, collapse) {
var childCount = this.model.getChildCount(cell);
for (var i = 0; i < childCount; i++) {
var child = this.model.getChildAt(cell, i);
var geo = this.getCellGeometry(child);
if (geo != null && geo.relative) {
return false;
}
}
return childCount > 0;
};
// Returns the relative position of the given child
function getRelativePosition(state, dx, dy) {
if (state != null) {
var model = graph.getModel();
var geo = model.getGeometry(state.cell);
if (geo != null && geo.relative && !model.isEdge(state.cell)) {
var parent = model.getParent(state.cell);
if (model.isVertex(parent)) {
var pstate = graph.view.getState(parent);
if (pstate != null) {
var scale = graph.view.scale;
var x = state.x + dx;
var y = state.y + dy;
if (geo.offset != null) {
x -= geo.offset.x * scale;
y -= geo.offset.y * scale;
}
x = (x - pstate.x) / pstate.width;
y = (y - pstate.y) / pstate.height;
if (Math.abs(y - 0.5) <= Math.abs((x - 0.5) / 2)) {
x = x > 0.5 ? 1 : 0;
y = Math.min(1, Math.max(0, y));
} else {
x = Math.min(1, Math.max(0, x));
y = y > 0.5 ? 1 : 0;
}
return new mxPoint(x, y);
}
}
}
}
return null;
}
// Replaces translation for relative children
graph.translateCell = function (cell, dx, dy) {
var rel = getRelativePosition(
this.view.getState(cell),
dx * graph.view.scale,
dy * graph.view.scale,
);
if (rel != null) {
var geo = this.model.getGeometry(cell);
if (geo != null && geo.relative) {
geo = geo.clone();
geo.x = rel.x;
geo.y = rel.y;
this.model.setGeometry(cell, geo);
}
} else {
mxGraph.prototype.translateCell.apply(this, arguments);
}
};
// Replaces move preview for relative children
graph.graphHandler.getDelta = function (me) {
var point = mxUtils.convertPoint(
this.graph.container,
me.getX(),
me.getY(),
);
var delta = new mxPoint(point.x - this.first.x, point.y - this.first.y);
if (this.cells != null && this.cells.length > 0 && this.cells[0] != null) {
var state = this.graph.view.getState(this.cells[0]);
var rel = getRelativePosition(state, delta.x, delta.y);
if (rel != null) {
var pstate = this.graph.view.getState(
this.graph.model.getParent(state.cell),
);
if (pstate != null) {
delta = new mxPoint(
pstate.x + pstate.width * rel.x - state.getCenterX(),
pstate.y + pstate.height * rel.y - state.getCenterY(),
);
}
}
}
return delta;
};
// Relative children cannot be removed from parent
graph.graphHandler.shouldRemoveCellsFromParent = function (
parent,
cells,
evt,
) {
return (
cells.length == 0 &&
!cells[0].geometry.relative &&
mxGraphHandler.prototype.shouldRemoveCellsFromParent.apply(
this,
arguments,
)
);
};
// Enables moving of relative children
graph.isCellLocked = function (cell) {
return false;
};
// Enables rubberband selection
new mxRubberband(graph);
// Gets the default parent for inserting new cells. This
// is normally the first child of the root (ie. layer 0).
var parent = graph.getDefaultParent();
// Adds cells to the model in a single step
graph.getModel().beginUpdate();
try {
var v1 = graph.insertVertex(parent, null, 'Process', 60, 60, 90, 40);
var v2 = graph.insertVertex(
v1,
null,
'in',
0,
0.5,
20,
20,
'fontSize=9;shape=ellipse;resizable=0;',
);
v2.geometry.offset = new mxPoint(-10, -10);
v2.geometry.relative = true;
var v3 = graph.insertVertex(
v1,
null,
'out',
1,
0.5,
20,
20,
'fontSize=9;shape=ellipse;resizable=0;',
);
v3.geometry.offset = new mxPoint(-10, -10);
v3.geometry.relative = true;
} finally {
// Updates the display
graph.getModel().endUpdate();
}
}
</script>
<template>
<div id="graphContainer"></div>
</template>
<style lang="less"></style>