2013-07-02 3 views
2

Итак, я хочу, чтобы создать конечное состояние машинно-визуализатор/редактор с помощью kineticjs и я спотыкаясь по следующему сценарию:KineticJS: Draw Стрелки между двумя формами

У меня есть два «узлы», скажем, круг-объекты (сгруппированные с меткой), которые перетаскиваются на моей сцене. Теперь я не хочу нажимать на один круг, удерживать мышь и перемещать ее и добавлять соединение (стрелка, ради простоты) между двумя фигурами.

Поэтому было бы здорово иметь какие-либо намеки на то, как это сделать, поскольку я еще не нашел решение.

Чтобы указать его: сами узлы должны оставаться перетаскиваемыми. Я подумал: добавьте черный круг и белый круг с чуть меньшим радиусом, сгруппируйте их. затем на dragstart белый круг -> узел перетаскивания, на dragstart черный круг -> нарисовать стрелку.

Проблема заключается в том, как нарисовать стрелку, начинающуюся с одной фигуры, и после мыши к ее цели (которая может быть другой связью nodegroup => с этой группой или пустой точкой сцены => открывается оверлей, что позволяет пользователь выбирает другой узел для рисования или отмены чертежа).

Надеюсь, это будет понятно. За дополнительной информацией, пожалуйста, не стесняйтесь спрашивать меня.

С наилучшими пожеланиями, Dominik

пс: Поведение, кажется, точно так же как поведение Lucidchart (точка ком) используется при создании диаграмм, так что, может быть, вы понимаете, что я хочу достичь лучше, глядя на их демо здесь: https://www.lucidchart.com/demo.

ответ

3

Во-первых, для простоты здесь является скрипку о том, как нарисовать базовую линию с помощью мыши и KineticJS: http://jsfiddle.net/projeqht/fF3hh/

Допустим, у вас уже есть два круга на сцене, и вам нужно, чтобы нарисовать линию для их соединения.

Мы можем использовать e.targetNode для выбора узлов на каждом событии (MouseDown, MouseUp), например:

layer.on("mousedown", function (e) { 
    var nodeDown = e.targetNode; 
} 

layer.on("mouseup", function (e) { 
    var nodeUp = e.targetNode; 
} 

Нам нужно проверить, если родитель nodeDown является Kinetic.Group или что-то другое ,

  1. Если целевой узел nodeDown имеет Kinetic.Group для родителей, мы можем использовать эту группу, чтобы сохранить новую строку, а второй целевой узел nodeUp.
  2. Если целевой узел nodeUp не имеет Kinetic.Group для родителя, нам нужно увидеть, есть ли у nodeUp группа для родителя. Если nodeUp имеет Kinetic.Group для родителя, мы можем использовать эту группу для хранения новой строки и первого целевого узла nodeDown.
  3. Если ни один из nodeDown или nodeUp не имеет группы для родителя, тогда нам нужно будет создать для них новую группу и добавить все три формы (2 круга и строку) в эту новую группу.

Используйте этот учебник, чтобы узнать, как перемещать фигуры из 1 группы в другую: http://www.html5canvastutorials.com/kineticjs/html5-canvas-move-shape-to-another-container-with-kineticjs/

Кроме того, если вы перемещаете фигуру из одной группы в другую, вы можете remove() или destroy() дополнительные группы, если он больше не нужен.

При рисовании линии вам придется отключить перетаскивание фигур, чтобы вы могли перетаскивать и рисовать мышью. Вы можете сделать это, делая что-то похожее на это:

function stopDrag() { 
    for (var i=0; i<layer.children.length; i++) { 
    layer.children[i].setDraggable(false); 
    } 
} 

function startDrag() { 
    for (var i=0; i<layer.children.length; i++) { 
     layer.children[i].setDraggable(true); 
    } 
} 

Это заставит все ребенок слоя перетаскиваемого и undraggable, но вы можете захотеть ограничить, что, будучи более конкретным, чем выберите layer.children. Приятным трюком, который мне нравилось использовать здесь, было имя всех групп, которые были перетаскиваемы как «draggable_shapes», а затем используйте var draggableArray = stage.get('.draggable_shapes'), чтобы выбрать все группы, которые разрешены для перетаскивания, затем вы можете пропустить этот массив и setDraggable().

Еще один момент, который следует отметить, заключается в том, что координаты X и Y линии будут немного сложными для расчета, в зависимости от того, имеет ли она группу в качестве родителя или слоя. Если линия сгруппирована, координаты линии будут относиться к позиции , иначе координаты линии будут относительно Этап (верхний левый угол).

Это позволит вам начать соединение линии с двумя разными кругами. Вам решать логику координат, если вы хотите, чтобы линии соединялись только на внешнем краю кругов.

Возможно, вы захотите добавить прозрачный прямоугольник (атрибут opacity: 0) за каждым кругом, чтобы на мульдауне с прямоугольником вы вызывали drawLine(), чтобы начать рисовать линию. Или, если пользователь нажимает на круг, он перетаскивает группу. По крайней мере, это имеет аналогичную функциональность для приложения ясных графиков.

Пользовательский Хит Функция (http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-custom-hit-function-tutorial/), вероятно, будет более чистым способом сделать это, но я не на 100% на использовании пользовательских функций Хит, кто-то еще может знать лучше.

Сообщите мне, если вам нужна дополнительная помощь. Удачи!

+0

Большое спасибо за этот ответ. Я попробую завтра, потому что сейчас у меня в голове большой узел. Я отметил ответ как принятый, потому что на первый взгляд все это кажется очень подробным и логичным для меня, так что еще раз, спасибо! :) – Dominik

+0

+1 для пользовательских функций хита. Это идеальный вариант использования для них –

+0

, поэтому он работает :) только для информации. Только проблема: используя touch-интерфейс, я получаю NaN только для x и y-координат. Любые идеи о том, как изменить код для реализации сенсорных координат? Я попробовал getTouchPosition() и снова getX и так далее, но это не сработало. – Dominik

Смежные вопросы