简体   繁体   中英

How to make an eraser with kineticjs

I was messing around with kineticjs and I was trying to build a mouse tool that lets you erase things on a single layer. I know I can make white lines if my background is white to give an "eraser" effect, but my problem is that my background is an image (they wont be erasing the background image), so drawing white lines simply wont erase it. I need to be able to actually erase parts of the line by mouse coordinates. Is there anyone that has done this or knows how

Yes, you can both draw freehand lines and use a freehand eraser in KineticJS.

However, the solution is modestly complex.

Prerequisite:

I'm assuming during your messing around you've learned how to listen to mouse events and save those mouseXY's in order to let the user "drag-draw" a polyline.

The solution:

The solution involves using a custom Kinetic.Shape which gives you more flexibility than the pre-defined Kinetic objects.

A Kinetic.Shape gives you a full canvas context to work with.

You can use context.moveTo and multiple context.lineTo to let the user drag-draw freehand lines.

With a full context, you also can use compositing.

Specifically, you can use “destination-out” compositing which causes any new line drawn to act as an eraser.

With "destination-out" ... any previously drawn lines are “erased” by the new line.

An outline of your solution:

  • Have the user drag-draw a polyline on the canvas by capturing all the individual points as they drag.
  • Capture whether the user was in “draw” or “erase” mode when dragging that line.
  • Use a custom Kinetic.Shape to either draw a line or use compositing to erase line.
  • In “draw” mode, set context.globalCompositeOperation=”source-over” and draw that line.
  • In “erase” mode, set context.globalCompositeOperation=”destination-out” drag an eraser.

One complication is that the context Kinetic.Shape gives you is a wrapper around a true canvas context.

It limits you to one context.beginPath and you can only use 1 composite mode per context.beginPath. Since you need to have multiple compositing modes (drawing vs eraser), you need to know how to get a true context canvas instead of Kinetic.Shapes wrapped context.

Here's how:

var sketchpad = new Kinetic.Shape({

    drawFunc: function(context) {

        // get a true canvas context, not a "wrapped" context
        context=this.getContext()._context;

        // save the context state
        context.save();

        // then you can use multiple beginPath's 
        // and therefore have multiple composites.

        context.beginPath();
        context.globalCompositeOperation="source-over";
        // draw a polyline using your saved line-points
        context.stroke();

        context.beginPath();
        context.globalCompositeOperation="destination-out";
        // draw a polyline which acts like an eraser
        context.stroke();


        // restore the context state
        context.restore();

    },
    stroke: 'black',
    strokeWidth: 4
});

"Is there anyone that has done this"

I'm afraid there isnt. The line which you have drawed is an object. Its simple to remove it as an whole object.

If you wan't use case like eraser it would be quit difficult to divide the line to several parts which stay in drawin and that part which does not.

How ever, if your line is a group of pixels that would be much easier, but group of pixels are not a line.

我知道这真的很晚,但是当我搜索橡皮擦时,我首先找到了此链接,但是我没有找到一个好的解决方案,所以我创建了一个新的解决方案,她的方法是: 如何使用dynamicjs 5.1.0制作橡皮擦在多层上表演?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM