问题描述
我创建了一个 codepen,它使用 jquery ui droppable(用于拖放)、jsPlumb(用于流程图)和 Panzoom(平移和缩放)来创建流程图构建器。您可以将列表项从可拖动容器(第一列)拖动到流程图(第二列),然后使用点连接这些项以创建流程图。 #flowchart 是一个 Panzoom 目标,同时启用了平移和缩放。这一切正常。
但是,我希望 #flowchart div 始终跨越流程图包装器的整个区域,即 #flowchart 应该是一个无限的画布,支持平移、缩放并且是一个可放置的容器。
它应该具有与 flowchart-builder-demo 相同的效果。画布是无限的,您可以在其中从右栏中拖放项目(问题、操作、输出)。
关于如何实现这一点的任何指示(如相关事件或多个 panzoom 元素和/或 css 更改)将不胜感激。
const BG_SRC_TGT = "#2C7BE5";
const HEX_SRC_ENDPOINT = BG_SRC_TGT;
const HEX_TGT_ENDPOINT = BG_SRC_TGT;
const HEX_ENDPOINT_HOVER = "#fd7e14";
const HEX_CONNECTOR = "#39afd1";
const HEX_CONNECTOR_HOVER = "#fd7e14";
const connectorPaintStyle = {
strokeWidth: 2,stroke: HEX_CONNECTOR,joinstyle: "round",outlinestroke: "white",outlinewidth: 1
},connectorHoverStyle = {
strokeWidth: 3,stroke: HEX_CONNECTOR_HOVER,outlinewidth: 2,outlinestroke: "white"
},endpointHoverStyle = {
fill: HEX_ENDPOINT_HOVER,stroke: HEX_ENDPOINT_HOVER
},sourceEndpoint = {
endpoint: "Dot",paintStyle: {
stroke: HEX_SRC_ENDPOINT,fill: "transparent",radius: 4,strokeWidth: 3
},isSource: true,connector: ["Flowchart",{ stub: [40,60],gap: 8,cornerRadius: 5,alwaysRespectStubs: true }],connectorStyle: connectorPaintStyle,hoverPaintStyle: endpointHoverStyle,connectorHoverStyle: connectorHoverStyle,dragOptions: {},overlays: [
["Label",{
location: [0.5,1.5],label: "Drag",cssClass: "endpointSourceLabel",visible: false
}]
]
},targetEndpoint = {
endpoint: "Dot",paintStyle: {
fill: HEX_TGT_ENDPOINT,radius: 5
},maxConnections: -1,dropOptions: { hoverClass: "hover",activeClass: "active" },isTarget: true,{ location: [0.5,-0.5],label: "Drop",cssClass: "endpointTargetLabel",visible: false }]
]
};
const getUniqueId = () => Math.random().toString(36).substring(2,8);
// Setup jquery ui draggable,droppable
$("li.list-group-item").draggable({
helper: "clone",zIndex: 100,scroll: false,start: function (event,ui) {
var width = event.target.getBoundingClientRect().width;
$(ui.helper).css({
'width': Math.ceil(width)
});
}
});
$('#flowchart').droppable({
hoverClass: "drop-hover",tolerance: "pointer",drop: function (event,ui) {
var helper = $(ui.helper);
var fieldId = getUniqueId();
var offset = $(this).offset(),x = event.pageX - offset.left,y = event.pageY - offset.top;
helper.find('div.field').clone(false)
.animate({ 'min-height': '40px',width: '180px' })
.css({ position: 'absolute',left: x,top: y })
.attr('id',fieldId)
.appendTo($(this)).fadeIn('fast',function () {
var field = $("#" + fieldId);
jsPlumbInstance.draggable(field,{
containment: "parent",scroll: true,grid: [5,5],stop: function (event,ui) {
}
});
field.addClass('panzoom-exclude');
var bottomEndpoints = ["BottomCenter"];
var topEndPoints = ["TopCenter"];
addEndpoints(fieldId,bottomEndpoints,topEndPoints);
jsPlumbInstance.revalidate(fieldId);
});
}
});
const addEndpoints = (toId,sourceAnchors,targetAnchors) => {
for (var i = 0; i < sourceAnchors.length; i++) {
var sourceUUID = toId + sourceAnchors[i];
jsPlumbInstance.addEndpoint(toId,sourceEndpoint,{ anchor: sourceAnchors[i],uuid: sourceUUID });
}
for (var j = 0; j < targetAnchors.length; j++) {
var targetUUID = toId + targetAnchors[j];
jsPlumbInstance.addEndpoint(toId,targetEndpoint,{ anchor: targetAnchors[j],uuid: targetUUID });
}
$('.jtk-endpoint').addClass('panzoom-exclude');
}
// Setup jsPlumbInstance
var jsPlumbInstance = jsPlumb.getInstance({
DragOptions: { cursor: 'pointer',zIndex: 12000 },ConnectionOverlays: [
["Arrow",{ location: 1 }],["Label",{
location: 0.1,id: "label",cssClass: "aLabel"
}]
],Container: 'flowchart'
});
// Setup Panzoom
const elem = document.getElementById('flowchart');
const panzoom = Panzoom(elem,{
excludeClass: 'panzoom-exclude',canvas: true
});
const parent = elem.parentElement;
parent.addEventListener('wheel',panzoom.zoomWithWheel);
解决方法
我刚刚在研究完全相同的问题,并发现这是唯一的答案
Implementing pan and zoom in jsPlumb
使用的 PanZoom 看起来很旧 - 但想法是一样的,使用 JQuery Draggable 插件来处理可移动元素,而不是内置的 JsPlumb 插件。这允许元素移出边界。
下面的可拖动功能使用 PanZoom 库为我修复了它。
var that = this;
var currentScale = 1;
var element = $('.element');
element.draggable({
start: function (e) {
//we need current scale factor to adjust coordinates of dragging element
currentScale = that.panzoom.getScale();
$(this).css("cursor","move");
that.panzoom.setOptions({ disablePan: true });
},drag: function (e,ui) {
ui.position.left = ui.position.left / currentScale;
ui.position.top = ui.position.top / currentScale;
if ($(this).hasClass("jtk-connected")) {
that.jsPlumbInstance.repaintEverything();
}
},stop: function (e,ui) {
var nodeId = $(this).attr('id');
that.jsPlumbInstance.repaintEverything();
$(this).css("cursor","");
that.panzoom.setOptions({ disablePan: false });
}
});
我不确定在拖动时重绘所有内容是否那么有效 - 所以也许只重绘两个连接元素。