Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a paper draggable

Tags:

jointjs

If the paper is too big for the div it's shown in, I'd like to make the paper draggable.

I tried the papers blank:pointerdown and pointerup events but was not able to just follow the mousemovement. I also tried to make the element of the paper draggable via jquery, but nothing seems to do the trick...

Is there any way to do this?

like image 229
Maria Avatar asked Feb 10 '15 12:02

Maria


3 Answers

This can be achieved with a combination of JointJS events and document events. The graph display is encapsulated in a div:

<div id='diagram'></div>

Then add the event handlers for JointJS, first the pointerdown event where we store the start position of the drag:

paper.on('blank:pointerdown',
    function(event, x, y) {
        dragStartPosition = { x: x, y: y};
    }
);

Then the end of the drag (pointerup) when we delete the variable we store the position in (it also acts as a flag whether there is an active drag in progress):

paper.on('cell:pointerup blank:pointerup', function(cellView, x, y) {
    delete dragStartPosition;
});

As JointJS does not expose a "paper pointer move" event, we need to use the mousemove document event. For example, with JQuery:

$("#diagram")
    .mousemove(function(event) {
        if (dragStartPosition)
            paper.translate(
                event.offsetX - dragStartPosition.x, 
                event.offsetY - dragStartPosition.y);
    });

We get the drag start coordinates and the current pointer position and update the paper position using the paper.translate() call.

WARNING: if you scale the paper (using paper.scale()), you have to also scale the starting position of the drag:

var scale = V(paper.viewport).scale();
dragStartPosition = { x: x * scale.sx, y: y * scale.sy};

The calls to paper.translate() will then update to the proper position.

like image 158
Michael Kleinhenz Avatar answered Feb 14 '23 15:02

Michael Kleinhenz


I know this is a slightly old thread, but I was stuck with this for a while and came across a neat solution using the SVG Pan and Zoom library. Git hub link here

EDIT - I created a plunker of the steps below (plus some extras) here: SVG panning with Jointjs

First step after creating the paper is to initialise SVG Pan and Zoom:

    panAndZoom = svgPanZoom(targetElement.childNodes[0], 
        {
            viewportSelector: targetElement.childNodes[0].childNodes[0],
            fit: false,
            zoomScaleSensitivity: 0.4,
            panEnabled: false
        });

Where targetElement is the div that the jointjs paper has gone into. Jointjs will create a SVG element within that (hence the childNodes[0]) and within that element the first element is the viewport tag (hence childNodes[0].childNodes[0] in the viewportselector). At this stage pan is disabled, because in my use case it would intefer with drag and drop elements on the paper. Instead what I do is keep a reference to the panAndZoom object and then switch pan on and off on the blank:pointerdown and blank:pointerup events:

paper.on('blank:pointerdown', function (evt, x, y) {
        panAndZoom.enablePan();
    });
paper.on('cell:pointerup blank:pointerup', function(cellView, event) {
            panAndZoom.disablePan();

});

Just another way of tackling the issue I guess, but I found it a bit easier, plus it gives you zoom too and you can adjust the sensitivity etc.

like image 38
Luke W Avatar answered Feb 14 '23 13:02

Luke W


I suggest the following:

  1. register a handler for the paper blank:pointerdown event that will initiate the paper dragging (store a flag which you'll use in your mousemove handler to recognize the paper is in the "panning" state).
  2. Put the big paper in a <div> container with CSS overflow: auto. This <div> will be your little window to the large paper.
  3. register a handler for document body mousemove event (because you most likely want the paper to be dragged even if the mouse cursor leaves the paper area?). In this handler, you'll be setting the scrollLeft and scrollTop properties of your <div> container making the paper "panning". For adjusting the scrollLeft and scrollTop properties, you'll use the clientX and clientY properties of the event object together with the same properties that you stored previously in your blank:pointerdown handler. (in other words, you need those to find the offset of the panning from the last mousemove/blank:pointerdown).
  4. register a handler for document body mouseup and in this handler, clear your paper dragging flag that you set in step 1.
like image 40
dave Avatar answered Feb 14 '23 13:02

dave