Как я могу удерживать клетки суставов от переполнения бумаги?

Я использую jointjs для создания диаграмм, которые будут редактироваться пользователем. Пользователь может перетащить их и переместить каждую ячейку. Однако, когда ячейка перетаскивается к краю, она переполняется и обрезается. Я хочу, чтобы это не происходило, вместо того, чтобы клетка останавливалась, прежде чем она попала на край бумаги, и ей не разрешили пересечь край, таким образом, всегда оставаясь полностью в бумаге. Поведение можно увидеть в собственных собственных демонах:

http://www.jointjs.com/tutorial/ports

Попробуйте перетащить ячейку на край, и вы увидите, что она со временем становится скрытой, когда она пересекает край бумажного элемента.

Во-вторых, я использую плагин для направленного макета графа, который находится здесь:

http://jointjs.com/rappid/docs/layout/directedGraph

Как вы можете видеть, позиция дерева автоматически перемещается в верхнем левом углу элемента бумаги всякий раз, когда вы нажимаете кнопку. Как изменить эти позиции по умолчанию? Единственными параметрами, которые я вижу для предоставленной функции, являются пространство между рангами и пространством между узлами, без начального положения. Скажем, я хотел, чтобы дерево появилось в середине бумаги, щелкнув "макет", где мне нужно было внести изменения? Заранее благодарим за любую помощь.

Ответ 1

Я думаю, что мой предыдущий ответ по-прежнему возможен, но именно так я реализовал его в своем проекте. Он имеет преимущество перед другим ответом в том, что он не требует от вас использования пользовательского elementView и кажется более простым (для меня).

(Работает jsfiddle: http://jsfiddle.net/pL68gs2m/2/)

На paper обработайте событие cell:pointermove. В обработчике событий создайте ограничивающий прямоугольник cellView, на котором было инициировано событие, и используйте его для ограничения движения.

var graph = new joint.dia.Graph;

var width = 400;
var height = 400;
var gridSize = 1;

var paper = new joint.dia.Paper({
    el: $('#paper'),
    width: width,
    height: height,
    model: graph,
    gridSize: gridSize
});

paper.on('cell:pointermove', function (cellView, evt, x, y) {

    var bbox = cellView.getBBox();
    var constrained = false;

    var constrainedX = x;

    if (bbox.x <= 0) { constrainedX = x + gridSize; constrained = true }
    if (bbox.x + bbox.width >= width) { constrainedX = x - gridSize; constrained = true }

    var constrainedY = y;

    if (bbox.y <= 0) {  constrainedY = y + gridSize; constrained = true }
    if (bbox.y + bbox.height >= height) { constrainedY = y - gridSize; constrained = true }

    //if you fire the event all the time you get a stack overflow
    if (constrained) { cellView.pointermove(evt, constrainedX, constrainedY) }
});

Ответ 2

я. Чтобы предотвратить переполнение элементов на бумаге, вы можете использовать опцию restrictTranslate для бумаги (JointJS v0.9.7 +).

paper.options.restrictTranslate = function(cellView) {
    // move element inside the bounding box of the paper element only
    return cellView.paper.getArea();
}

http://jointjs.com/api#joint.dia.Paper:options

II. Используйте опции marginX и marginY DirectedGraph для перемещения левого верхнего угла результирующего графика, то есть добавьте маржу слева и сверху.

http://jointjs.com/rappid/docs/layout/directedGraph#configuration

Ответ 3

В качестве дополнения к римскому ответу restrictTranslate также можно настроить как true, чтобы ограничить перемещение элементов до границы области бумаги.

Пример:

var paper = new joint.dia.Paper({
    el: $('#paper'),
    width: 600,
    height: 400,
    model: graph,
    restrictTranslate: true
})

Ответ 4

Изменить: Я думаю, что этот подход по-прежнему возможен, но теперь я думаю, что мой другой ответ проще/лучше.

Документы JointJS предоставляют образец, в котором перемещение формы ограничено, чтобы лежать на эллипсе:

http://www.jointjs.com/tutorial/constraint-move-to-circle

Работает

  • Определение нового представления для вашего элемента, расширение joint.dia.ElementView
  • Перекрытие событий pointerdown и pointermove в представлении для реализации ограничения. Это делается путем вычисления новой позиции на основе положения мыши и ограничения, а затем передачи этого в базовый обработчик событий ElementView
  • Принудительное использование paper для использования пользовательского представления элемента

Этот подход может быть легко адаптирован для предотвращения вытягивания фигуры с края бумаги. На шаге 2 вместо вычисления пересечения с эллипсом, как в учебнике, вы должны использовать Math.min() или Math.max() для вычисления новой позиции.