Search code examples
javascripteventsdom-eventspaperjs

Paper.js Layer Event versus Tool Event - Different Behavior


Note these two sketches, one which has the expected and desired behavior, and one which does not. When you open these sketches you will see an image with some text on it. The text is draggable to a new position. The image should stay stationery during the repositioning. In the first sketch it does, in the second it doesn't.

The difference in the code between the two sketches is that in the first one the event is established on the active layer:

project.activeLayer.onMouseDrag = function(event) {
    view.center = changeCenter(paper.view.center, event.delta.x, event.delta.y, 0.7);
}

In the second one it is established on what I understand to be the global paper.tool:

function onMouseDrag(event) {
    view.center = changeCenter(paper.view.center, event.delta.x, event.delta.y, 0.7);
}

It seems to me it shouldn't matter because in the text mousedrag listener I'm stopping propagation of the event:

event.stopPropagation();

However, this only seems to take effect in the first sketch, not the second one. Why is this the case?


Solution

  • The difference is that declaring the "global" function onMouseDrag causes paper to create a Tool and the tool event gets called at the end of the processing regardless of whether the normal handlers chain requested that propagation be stopped. (I say "global" because when paper executes paper script it wraps your code in a function with its own scope. It then passes those "global" functions back to paper in an object returned from that function.) If any "global" functions were declared paper then creates a tool that handles them. And that tool gets called at the end of event processing regardless of whether your handler terminates processing or not.

    The following code is the relevant code in paper's View.js module:

    function handleMouseMove(view, point, event) {
        view._handleEvent('mousemove', point, event);
        var tool = view._scope.tool;
        if (tool) {
            tool._handleEvent(dragging && tool.responds('mousedrag')
                    ? 'mousedrag' : 'mousemove', point, event);
        }
        view.update();
        return tool;
    }
    

    The item's handler (your PointText handler) is being called by view._handleEvent() while the tool that was implicitly created by defining the "global" onMouseDrag is called regardless of the outcome of view._handleEvent processing.

    This problem only comes up if you're using paperscript and you declare one of the global functions, e.g., onMouseDrag.