Steps for crafting an eraser in EaselJS

Currently, I am working on a canvas painting project and looking to add an eraser tool. However, when attempting to erase content using the provided lines of code, it ends up clearing the entire canvas instead.

//undo tool
var undo = new createjs.Bitmap(app.loader.getResult('undo'));
undo.name = 'undo';
undo.x = brush.x + 90;
undo.y = brush.y;
undo.addEventListener('click', this.undoHandler); 
this.toolsContainer.addChild(undo); 

//trash tool
var clear = new createjs.Bitmap(app.loader.getResult('clear'));
clear.name = 'clear';
clear.x = undo.x + 90;
clear.y = undo.y;
clear.addEventListener('click', this.clearHandler); 
this.toolsContainer.addChild(clear);

undoHandler:function(){

if(tools.undoArray.length){
    var lastItem = tools.undoArray.pop();
    app.container.removeChild(lastItem);        

    var lastItem2 = tools.undoArray2.pop();
    app.container.removeChild(lastItem2);

    var lastItem3 = tools.undoArray3.pop();
    app.container.removeChild(lastItem3);

    app.stage.update();
}

}, 

clearHandler:function(){
    app.container.removeAllChildren();
    app.container.updateCache(clearhandler?"destination-out":"source-over");;
    app.stage.update();
},

I aiming to create an eraser functionality similar to the one demonstrated in this example:

http://jsfiddle.net/lannymcnie/ZNYPD/

Any suggestions or ideas on how to achieve this?

Answer №1

Check out this

http://jsfiddle.net/lannymcnie/ZNYPD/
, where the essential code snippet is:

wrapper.updateCache(erase ? "destination-out" : "source-over");

thus...

var stage, wrapper, erase;

function init() {
    var stage = new createjs.Stage("canvas");
    createjs.Ticker.addEventListener("tick", stage);

    // Add text to draw on top of (along with instructions)
    stage.addChild(new createjs.Text("Click and Drag to Draw", "40px Arial", "#000000").set({x:200,y:200}));

    // Set up the container for drawing and mouse events
    var wrapper = new createjs.Container();
    wrapper.hitArea = new createjs.Shape(new createjs.Graphics().f("#000").dr(0,0,800,600));
    wrapper.cache(0,0,800,600); // Cache it.
    stage.addChild(wrapper);

    // Create the shape for drawing
    var drawing = new createjs.Shape();
    wrapper.addChild(drawing);

    var lastPoint = new createjs.Point();

    wrapper.addEventListener("mousedown", function(event) {

        // Store the position since we clear the graphics later
        lastPoint.x = event.stageX;
        lastPoint.y = event.stageY;

        erase = Math.floor(Math.random()*2);

        wrapper.addEventListener("pressmove", function(event){
            // Draw a round line from the last position to the current one
            drawing.graphics.ss(20, "round").s("#ff0000");
            drawing.graphics.mt(lastPoint.x, lastPoint.y);        
            drawing.graphics.lt(event.stageX, event.stageY);

            // Update the last position for next move
            lastPoint.x = event.stageX;
            lastPoint.y = event.stageY;

            // Draw onto the canvas, then update the container cache

            wrapper.updateCache(erase == 1 ? "destination-out" : "source-over");
            drawing.graphics.clear();
        });

        // Listen for mousemove
    });
}
$(function(){
    init();
})

The only change is that the drawing is based on a random value between 0 and 1; in my example, the erase variable gets these values like so: erase = Math.floor(Math.random()*2);

Answer №2

To achieve this effect, I have implemented a technique using an array of midpoints and the globalCompositeOperation feature to create a transparent eraser trail.

Below is the code snippet that should be used in conjunction with a mouse move function:


var handleMouseMove = function (event) {
    midPt = new createjs.Point(oldPt.x + stage.mouseX>>1, oldPt.y+stage.mouseY>>1);

    if(curTool.type=="eraser"){

        var tempcanvas = document.getElementById('drawcanvas');
        var tempctx=tempcanvas.getContext("2d");
        
        tempctx.beginPath();
        tempctx.globalCompositeOperation = "destination-out";   
        tempctx.arc(midPt.x, midPt.y, 20, 0, Math.PI * 2, false);     
        tempctx.fill();
        tempctx.closePath();
        tempctx.globalCompositeOperation = "source-over";
        drawingCanvas.graphics.clear();

        // continuously update the midpoint arrays
        arrMidPtx.push(midPt.x);
        arrMidPty.push(midPt.y);
        stage.addChild(drawingCanvas);
        stage.update();

    }

    else if (curTool.type=="pen"){

        drawingCanvas.graphics.clear().setStrokeStyle(stroke, 'round', 'round').beginStroke(color).moveTo(midPt.x, midPt.y).curveTo(oldPt.x, oldPt.y, oldMidPt.x, oldMidPt.y);

        arrMidPtx.push(midPt.x);
        arrMidPty.push(midPt.y);
        arrOldPtx.push(oldPt.x);
        arrOldPty.push(oldPt.y);
        arrOldMidPtx.push(oldMidPt.x);
        arrOldMidPty.push(oldMidPt.y);

        oldPt.x = stage.mouseX;
        oldPt.y = stage.mouseY;
        oldMidPt.x = midPt.x;
        oldMidPt.y = midPt.y;

        stage.addChild(drawingCanvas);
        stage.update();
    }
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilize Discord.js v13 to stream audio directly from a specified URL

Can anyone help me figure out how to play audio from a URL using discord.js v13? I attempted this code but it's not working as expected. const connection = joinVoiceChannel({ channelId: voiceChannel.id, guildId: message.guild.id, adapterCreator ...

Having an issue with TypeScript and React where the onChange event on the <select> element is only setting the previous value instead of the current value when using the useState hook

I'm currently developing a scheduling web tool. One of the key features I'm working on involves calculating the total hours between two selected times, startTime and endTime. These times are chosen via a form and stored using the useState hook: ...

Guide to attaching a mouse click event listener to a child element within a Polymer custom component

I'm currently facing an issue where I am attempting to attach a click listener to one of the buttons within a custom element during the "created" life cycle callback (even attempted using the "ready" callback with the same outcome). Unfortunately, I ...

Parsing Json data efficiently by utilizing nested loops

I have 2 different collections of JSON data, but I'm unsure of how to utilize JavaScript to parse the information. Data from API1 is stored in a variable named response1: [{"placeid":1,"place_name":"arora-square","city":"miami","state":"florida","c ...

Unable to instantiate FormData with the constructor

Within my Angular application, I have a basic form setup like this: <form [formGroup]="loginForm" (submit)="login()"> <div id="container-credentials"> <input type="text" name="username" formControlName="username"> <input typ ...

Emails can be sent through a form without the need for refreshing

I am currently working on a webpage that utilizes parallax scrolling, and the contact box is located in the last section. However, I encountered an issue where using a simple HTML + PHP contact box would cause the page to refresh back to the first section ...

Modify the border in jQuery if a specific div exists within a list item

Here is a collection of items: <div class="wine"> <H1>Title</H1> <div class="promotion"></div></div> <div class="wine"> <H1>Title</H1> </div></div> <div class="wine"> <H1>Title& ...

How to set the selected value in an md-select using Angular Material

I'm encountering an issue while trying to set the selected value of md-select. Upon opening the page, I expect to see the pre-set category of the stock, but instead, all of them have the same category set. Furthermore, I'm unable to change the c ...

The error message "ReferenceError: cloudSky is not defined when attempting to use csZbar" indicates that the

Currently, I am attempting to utilize the csZbar plugin from this repository: csZbar However, following the instructions provided in the GitHub repository seems to be causing an issue: var app = angular.module('starter', ['ionic']) a ...

Using the useState hook will help avoid any crashes when running on IE11

I recently added a new repository to my GitHub account. The file dist/index.htm is causing Internet Explorer 11 to crash, displaying the error message: "unable to get property 'root' of undefined or null reference." This issue arises when I u ...

Using backslashes to escape JSON values within a value in Angular

When retrieving JSON data from the backend, I often encounter an issue where the value is set to "key": "\$hello" and it results in an "Unexpected token d". Is there a way in Angular to handle or escape these characters once received from the server? ...

How can I transfer Gmail message using express rendering parameters?

Using passport-google-oauth for authentication and the node-gmail-api for fetching gmail, I aim to display gmail message after authentication. In order to achieve this, I have written the following code in routes.js: app.get('/profile', isLogged ...

Expanding Bootstrap 5 navbar-nav to occupy entire screen space in collapsed state

Hello everyone, I hope you are doing well! I am currently working on a website project using Bootstrap 5 and have encountered an issue with the navbar toggler. While the toggler is functioning properly, I am having trouble making it fill the full width o ...

Changes made to an Array are not reflected in AngularJS data-ng-repeat

I have created a custom directive that displays notes left by users for a product. The directive contains a div that shows all the notes stored in the $scope.MessageList. <mx-note-manager-two isModalPopup="true" is-show-date-range="{{IsSh ...

What is the best way to extract value from a JSON object with jQuery?

How can I retrieve the value of 'FRI' from the JSON feed returned by an AJAX call using jQuery? $.ajax({ url: query, type: "GET", dataType: "json" success: function(data) { var day = // extract data value from JSON ...

Count the occurrences of x.status being equal to 10 in AngularJS

I have 3 different statuses: 10, 20, and 30. I am trying to determine how many times x.status equals 10 and display that count. My initial approach was something like this: count="x.status" where="x.status == 10" Count: {{value}} <!DOCTYPE html> ...

What is the best way to preload $templateCache before setting up routes in app.config?

Within my AngularJS application, I am currently in the process of constructing a build using grunt along with several essential plug-ins. grunt-contrib-clean grunt-contrib-requirejs grunt-angular-templates grunt-angular-copy I have successfully generat ...

Angular JS element cannot be located

My Angular object is not being passed when I write a new function, and I'm unsure why. The object, named person, is directly bound in the HTML and returns 2 items from the cardsCollection array. The function I'm attempting to create is called cl ...

Looking to reduce the size of a logo image within a container as you scroll down a webpage?

I've been working on creating a logo section for my website, but I'm struggling to make it shrink as users scroll down and expand back to its original size when they scroll up. I've tried various JavaScript and jQuery functions without succe ...

Unable to view the HTML division

I am struggling with my website creation as I encounter issues with the .Main div. Despite setting background-color: orange; in the CSS, the color is not visible on the page. The inspector shows that it is positioned at 1440 x 0. Any assistance would be gr ...