1

我创建了一个codepen,它使用 jquery ui droppable(用于拖放)、jsPlumb(用于流程图)和 Panzoom(平移和缩放)来创建流程图构建器。您可以将列表项从可拖动容器(第一列)拖动到流程图(第二列),然后使用点连接项目以创建流程图。#flowchart 是启用了平移和缩放的 Panzoom 目标。这一切都很好。

但是,我希望#flowchart div 始终跨越流程图包装的整个区域,即#flowchart 应该是支持平移、缩放并且是可放置容器的无限画布。

它应该具有与流程图构建器演示相同的效果。那里的画布是无限的,您可以在其中从右列拖放项目(问题、操作、输出)。

任何关于如何实现这一点的指针(如相关事件或多个 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
        },
        hoverPaintStyle: endpointHoverStyle,
        maxConnections: -1,
        dropOptions: { hoverClass: "hover", activeClass: "active" },
        isTarget: true,
        overlays: [
            ["Label", { 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);
4

1 回答 1

0

我一直在研究完全相同的问题,并认为这是唯一的答案

在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 });
            }
        });

我不确定在拖动时重绘所有内容是否有效 - 所以也许只是重绘两个连接元素。

于 2021-01-04T16:15:20.383 回答