-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
eraser for fabric.js #5188
Comments
This is a good question.. when a path is created, the object will contain multiple properties that describe the movement of the pen, which might make it very tricky to erase par of the path on the actual object. The eraser could draw on top, the same colour as the background or even better just implement an Undo? But interested to hear what solutions are out there. |
fabric does not support erasing tool. It does support clipPath object that can be a series of brushes and those can delete part of r |
@walljser 用globalCompositeOperation |
@asturur one more question,we know there are some objects on a fabric canvas,so can I merge them as a single layer correctly?(a fabric canvas with one image object), I think it is good for the users to look for a solution here,better then Stack Overflow~while, I will give some comments for other users. By the way, it is not so easy to learn the API ... |
You can group all paths, cloneAsImage and replace with actual paths and then you can make it look like erasing with global composite operation and free drawing mode on another canvas maybe. I have implemented such feature but cant give as a example because code quality is very poor. |
While i understand it takes some time to learn the api and an object based drawing logic, i still send people on stackoverflow. This is an hobby, free time project, that requires lot of time. Having people coming here for an how to, is a problem because the standard behaviour is open a new issue without searching. And i have to manage all the open issues. And is overwhelming. There are people that like to help on stackoverflow, and if you open a quality question, with a working snippet (not a fiddle link) you'll get an answer, often from me. The fiddle and the clear statement of the problem are asked in the issue template that very few people use. Another alternative is to learn how the fabricjs.com repository work, start with a demo page of the feature you would like to understand how to build and let someone complete it, at least at the end we have a demo page for the website that will have higher visibility. |
u have done a good job, Ultraman , i like Naruto ^ ^ |
i m another generation! |
haha, I am back, don't worry, just try to figure out https://codepen.io/kangax/pen/lpAnD on a fabric canvas, can u show me a sample?(freedrawingBrush better) |
@komagic 你好,用globalCompositionOperation, 我绘制的东西要拖动怎么办? |
@brightertools Hello, eraser's color can be the same as the background. but everything I painted can be selected and dragged.It will make mistakes. |
@walljser Sure, Just trying to provide some ideas, but see the issue there. The clipPath solution looks promising but to do it properly probably requires some clever code to remove paths. |
@walljser 完全不影响吧,我最近也在做一个项目就是这么做的,但是由于公司保密原因并不能把方法给你看,但是可以告诉你在mouse:move的时候可以使用fabric.Point+relativePan方法, |
支持随意拖拽,放大缩小 |
I have an eraser tool that does a "pseudo" erase of a free sketch path. Maybe this code is useful to you. There is some irrelevant code here, but which might help you understand the context: f.on('path:created', function(e) {
undos = [];
$toolbar.find('.sv_btn_sketch_undo').removeClass('disabled');
$toolbar.find('.sv_btn_sketch_redo').addClass('disabled');
if ($toolbar.find('.sv_btn_sketch_tool_eraser').hasClass('active')) {
e.path.globalCompositeOperation = 'destination-out';
f.renderAll();
} Also, when the eraser tool is selected, the path color is set to red, so while the user is "erasing" they will see a red path. (Fortunately, my sketches are only black on white, so the red creates no problem). Once the path is rendered, though, the destination-out composite operation will erase the underlying pixels. So, you get a true erase on the canvas, but not in the vector representation. Serialize/deserialize works as one might expect, including SVG. The original path(s) will be rendered, and when an "erase" path comes along, it will erase the pixels underneath. This actually has a bonus in our particular use case - at some point we will want to be able to animate an SVG showing the actions of a student creating a sketch. So, you will be able to see what they originally sketched - realized they made a mistake, and then used the erase tool - all in original sequence. Example result of a vertical line, with a horizontal "erasure" near the center: {"version":"2.4.1","objects":[{"type":"path","version":"2.4.1","originX":"left","originY":"top","left":217.55859375,"top":51.99321093750001,"width":0,"height":123.01,"fill":null,"stroke":"black","strokeWidth":2.88,"strokeDashArray":null,"strokeLineCap":"round","strokeLineJoin":"round","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"path":[["M",219,53.4346171875],["Q",219,53.4375,219,54.9375],["Q",219,56.4375,219,61.4375],["Q",219,66.4375,219,74.9375],["Q",219,83.4375,219,92.4375],["Q",219,101.4375,219,109.4375],["Q",219,117.4375,219,121.9375],["Q",219,126.4375,219,131.4375],["Q",219,136.4375,219,140.9375],["Q",219,145.4375,219,148.9375],["Q",219,152.4375,219,155.9375],["Q",219,159.4375,219,162.4375],["Q",219,165.4375,219,167.9375],["Q",219,170.4375,219,171.9375],["Q",219,173.4375,219,174.4375],["Q",219,175.4375,219,175.9375],["L",219,176.4403828125]]},{"type":"path","version":"2.4.1","originX":"left","originY":"top","left":129.44568750000002,"top":86.90625,"width":133.05,"height":1,"fill":null,"stroke":"red","strokeWidth":23.06,"strokeDashArray":null,"strokeLineCap":"round","strokeLineJoin":"round","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"destination-out","transformMatrix":null,"skewX":0,"skewY":0,"path":[["M",274.0230625,99.4375],["Q",274,99.4375,273.5,99.4375],["Q",273,99.4375,268,99.4375],["Q",263,99.4375,255,99.4375],["Q",247,99.4375,240,99.4375],["Q",233,99.4375,222.5,99.4375],["Q",212,99.4375,203,99.4375],["Q",194,99.4375,186.5,99.4375],["Q",179,99.4375,172.5,99.4375],["Q",166,99.4375,161.5,98.9375],["Q",157,98.4375,153,98.4375],["Q",149,98.4375,146,98.4375],["Q",143,98.4375,142,98.4375],["L",140.9769375,98.4375]]}]} <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="369" height="369" viewBox="0 0 369 369" xml:space="preserve">
<desc>Created with Fabric.js 2.4.1</desc>
<defs>
</defs>
<path d="M 219 53.4346171875 Q 219 53.4375 219 54.9375 Q 219 56.4375 219 61.4375 Q 219 66.4375 219 74.9375 Q 219 83.4375 219 92.4375 Q 219 101.4375 219 109.4375 Q 219 117.4375 219 121.9375 Q 219 126.4375 219 131.4375 Q 219 136.4375 219 140.9375 Q 219 145.4375 219 148.9375 Q 219 152.4375 219 155.9375 Q 219 159.4375 219 162.4375 Q 219 165.4375 219 167.9375 Q 219 170.4375 219 171.9375 Q 219 173.4375 219 174.4375 Q 219 175.4375 219 175.9375 L 219 176.4403828125" style="stroke: rgb(0,0,0); stroke-width: 2.88; stroke-dasharray: none; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(219 114.94) translate(-219, -114.9375) " stroke-linecap="round" />
<path d="M 274.0230625 99.4375 Q 274 99.4375 273.5 99.4375 Q 273 99.4375 268 99.4375 Q 263 99.4375 255 99.4375 Q 247 99.4375 240 99.4375 Q 233 99.4375 222.5 99.4375 Q 212 99.4375 203 99.4375 Q 194 99.4375 186.5 99.4375 Q 179 99.4375 172.5 99.4375 Q 166 99.4375 161.5 98.9375 Q 157 98.4375 153 98.4375 Q 149 98.4375 146 98.4375 Q 143 98.4375 142 98.4375 L 140.9769375 98.4375" style="stroke: rgb(255,0,0); stroke-width: 23.06; stroke-dasharray: none; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(207.5 98.94) translate(-207.5, -98.9375) " stroke-linecap="round" />
</svg> The stroke color is irrelevant in the ultimate result - you could set it to transparent. We prefer red, as red will be rendered while the user is sketching the "erasure", and then when the stroke is finalized and rendered, the destination-out operation is performed and performs the "erase". If you read out the bitmap for other purposes (as we do) the pixels have truly been erased. |
that's all~ very simple |
as soon as clipPath is more mature, this effect will be possible. For now this is out of scope as a library function. if someone wants to contribute a demo to fabricjs.com could do it. |
check the fabricjs.com repository in this same organization. github.com/fabricjs/fabricjs.com |
@asturur I have created a pull request |
|
Hello:
now, I'm trying to use fabric.js to develop a free drawing board, but I have difficulty in creating a eraser. I don't know how to erase a part of a object which has been put in fabric Canvas, and then this object is still selectable and removable.
how to realize this feature.
The text was updated successfully, but these errors were encountered: