How to Remove Smooth Path on Double Click on it (for touch screen devices) in PaperJS

133 Views Asked by At

Checking the previous solution from a touch screen device (my mobile phone), I noticed the impossibility to select a PaperJS item by using onMouseMove event and so set the item as value for the selectedPath variable. Other problem, for a mobile device, is the difficulty to press the d key on the keyboard to delete the selectedPath...

So I thought to use the onDoubleClick event on an added item to remove it, like in this sketch where you can draw an arrow by dragging and make it yellow with a single click or remove it with a double click on it (you can also remove the rectangle with a double click on it), but can't achieve the same in this other sketch (similar to the previous question), to remove a smooth item (drawn dragging on canvas) on double click.

Thank you for your help

2

There are 2 best solutions below

0
On BEST ANSWER

An improvement has come for my request. Here the scketch of my solution:

JS code:

    var script = document.createElement('script');
    script.src = 'https://code.jquery.com/jquery-3.6.0.min.js';
    script.type = 'text/javascript';
    document.getElementsByTagName('head')[0].appendChild(script);
    
    tool.minDistance = 2;
    
    var path;
    var selections = [];
    
    function onMouseDown(event) {
        var lightness = (Math.random() - 0.5) * 0.4 + 0.4;
        var hue = Math.random() * 360;
        path = new Path({
            strokeWidth: 2,
            strokeColor: 'black',
            strokeCap: 'round',
            strokeJoin: 'round',
            fillColor: { hue: hue, saturation: 1, lightness: lightness },
            fullySelected: true,
            closed: true
        });
        path.fillColor.alpha = 0.5;
    
        if (path) {
            path.selected = false;
        }
    
        return path;
    }
    
    function onMouseMove(event) {
        project.activeLayer.strokeColor = 'black';
        if (event.item) {
            event.item.strokeColor = 'yellow';
        }
    }
    
    const myMap = [];
    function onMouseDrag(event) {
        path.add(event.point);
        
        myMap.push("x:" + event.point.x + ", y: " + event.point.y);
        console.log("Coordinates of control point P" + myMap.length + ": X = " + Number((path.lastSegment.point.x).toFixed(0)) + ", Y = " + Number((path.lastSegment.point.y).toFixed(0)));
    }
    
    function onMouseUp(event) {
        myMap.length = 0;
    }
            
    (function( $ ){
        $.fn.myfunction = function() {
            $( "#canvas" ).mouseup(function() {
                if (path == undefined) {
                    return true;
                }
                
                var selection = path;
                
                selection.smooth({
                    type: 'catmull-rom',
                    factor: 0.5
                });
                
                selection.onClick = function() {
                    this.bringToFront();
                }
                   
                selection.onDoubleClick = function(event) {
                    this.remove();
                }
    
                selections.push(selection);
            });
    
            return this;
        }; 
    })( jQuery );
    
    $('#canvas').myfunction(path);

but I notice that, although from a PC everything seems to work, visiting the sketch from a smartphone instead there is no action to either single or double clicks. The single click should bring the clicked element to the front, while the double click should remove it from the canvas. I do not know if it is a bug of the PaperJS sketcher, which does not perceive the touch as a click on devices with touch screens (to be submitted on GitHub and maybe implementable in my code with some external library that gives PaperJS the support of touch as a click) or if there is any error in my code.

Any suggestions are welcome, thank you.

0
On

What is happening is that when you want to delete an existing item by double clicking it, you also unwantedly trigger you mousedown listener, which is used to draw new items and should not be triggered in this case.
What you need to do is check whether you are over an existing item or not before starting drawing.

Here's a sketch demonstrating a simple solution to your issue.

document.addEventListener('touchmove', function(event) {
    event.preventDefault();
}, false);

var path;
let selectedPath;

// The mouse has to drag at least 20pt
// before the next drag event is fired:
tool.minDistance = 20;

function onMouseDown(event) {
    // If the mouse is pressed over an existing item, cancel drawing.
    if (event.item) {
        return;
    }
    path = new Path();
    path.strokeWidth = 4;
    path.strokeColor = 'black';
    path.fillColor = 'red';
    path.selected = true;
    path.closed = true;
    path.onClick = function() {
        this.strokeColor = 'yellow';
    };
    path.onDoubleClick = function() {
        this.remove();
    };
}

function onMouseDrag(event) {
    if (path) {
        path.add(event.point);
    }
}

function onMouseUp(event) {
    if (path) {
        path.selected = false;
        path.smooth();
        path = null;
    }
}

function onMouseMove(event) {
    project.activeLayer.selected = false;
    if (event.item) {
        event.item.selected = true;
        selectedPath = event.item;
    } else {
        selectedPath = null;
    }
}

function onKeyDown(event) {
    if (selectedPath && event.key == 'd') {
        selectedPath.remove();
    }
}

If you want to be able to draw a new shape, even when your pointer is over an existing shape, you will have to introduce a more complex strategy to understand the user intention. Let me know, and maybe open a new thread if you need this and don't manage to do it.