Closed AndrewJDR closed 4 years ago
So as intention to support it, i bought a ms surface 4 pad, just for that. The time to dive into the topic is missing
Some day I may be able to take a look (though I'm short on time myself, these days).
One question -- does fabric already have the ability to represent lines/paint brushes that change in width along the length of the stroke? For example, a line may start out at a thinkness of 1.2, then increase to 1.4, then decrease down to 0.9, etc. Putting pressure support aside, can fabric represent this kind of stroke, currently?
no it does not, that would need a special class, derived from path probably.
Just to make it clear, brush are pieces of code ( in fabricJS ) that have a method to handle mouse down/move/up, they can draw custom stuff since they have a render method, but when they finish, the end result must be handled by a fabric.Object derived class.
So other than the pressure code, the brush code, you need the object code. This is a big feature. It could be also be handled with a series of path of different strokeWidths grouped togheter. in that case you would need just a particular brush code.
Okay, thanks. I better understand what's involved, at least :) I think the quantization would be too obvious looking with the multiple strokes method, so a custom object that represents a smooth interpolation between a set of thickness values would probably be needed. If I do get some time to work on it some day, I will post here.
After almost a year since this issue was opened, I came up with the same motivation and has just started to implement a simple custom brush and path.
The pull request #5587 is the first step toward the goal, allowing the brush to access pressure
values, as well as x
and y
coordinates through fabric.util.getPointer
method.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Since I contributed to #5587 and #5589, I have continued my effort to implement a pressure-sensitive brush, and it’s somehow working as intended. I’ve tested it on iPad (Safari and Chrome) and Surface Go (Edge). It’s not yet open-sourced, but you could get the idea below:
@arcatdmz That's awesome!! Curious, how is it represented in vector terms, a series of separate smaller segments of different widths, or something else?
@AndrewJDR Thanks! Your guess is right, one stroke consists of multiple separate segments. To make it look smooth, a path simplification algorithm is applied to the raw stroke data at the end of each stroke (onMouseUp).
@arcatdmz That's very cool, do you plan to contribute that back to the fabric repo or somewhere else on github?
Hi @AndrewJDR , as i said before, if you want to contribute it, open a pr in early stage, so that we can start to look at code for integration before is done and maybe your time allotment for it is finished. Looks nice.
@asturur oh this is not my work, it’s @arcatdmz code... so I was wondering if they plan to open it :)
sorry i confused message order and nicknames
Hi all, thanks for your positive comments. I do wish to open a PR but it would be in March since I'm a bit busy this week.
that is fine by me! We could find a way to link that clearly in examples/readme.
I've noticed v4 is being developed and its beta version has been already released. Regarding the pressure-sensitive brush library, let me make sure that it can be used with v4.
Nothing should have changed in that case, the new item i think it allows you to use pressure events on controls, although i have no idea how you can use them.
I still need to work on documentations, but the basic features are working properly with v3.
@asturur @AndrewJDR I've completed the API document and other publication materials, I think.
@asturur Please let me know if there's anything I could do to include links to any of these in the Fabric.js official documents, as you've said so:
We could find a way to link that clearly in examples/readme.
@arcatdmz if you want to have a look at how i m building demo pages now: https://raw.githubusercontent.com/fabricjs/fabricjs.com/gh-pages/posts/demos/_posts/2020-2-15-custom-control-render.md and how it looks like: http://fabricjs.com/custom-control-render
you can build a demo based on that. As you see the embed prefill from codepen allow you to link external libraries easily and to have an editable demo. You can write a demo page for fabricjs.com, a simple one.
We can also have in the tutorial section how to build a custom brush
Hello, I am working on a drawing app similar to Chrome Canvas or the Google Keep Drawing Area. I want the free drawing brush width to be velocity sensitive (thus in a way simulating pressure) ie, when the mouse velocity increases, I want the brush stroke to get thicker. I stumbled on to this issue, and after some reading and research, I overrided the freedrawingBrush methods and broke down the path segments into smaller subsegments with width according to the speed.
But I'm having trouble regarding how to simplify or smooth out the different paths and their widths, so that it all looks like a single smooth curve.
@asturur @AndrewJDR @arcatdmz any suggestions or help?
Well how are you breaking up the segents? are those linear now? or still cubic curves?
I guess my code helps here. If you go with the "smaller sub-segments" approach, I would suggest the following:
mousedown
event.)To simplify the path, I rewrote a simplification library in TypeScript and extended it to take pressure values into consideration.
You can check the actual behavior in the demo site: https://arch-inc.github.io/fabricjs-psbrush/
btw I've finally managed to start working on the demo page for fabricjs-psbrush
.
For anyone looking for a quick and well-made solution, I just pass the array of points (x, y, pressure) to https://github.com/steveruizok/perfect-freehand then render it as SVG path commands. The result is perfect and easy to implement, supporting stylus pressure and falling back to velocity (distance of points) estimation on mouse/touch.
Drawn with MBP trackpad:
should include this integrstion in my brush docs
For anyone looking for a quick and well-made solution, I just pass the array of points (x, y, pressure) to https://github.com/steveruizok/perfect-freehand then render it as SVG path commands. The result is perfect and easy to implement, supporting stylus pressure and falling back to velocity (distance of points) estimation on mouse/touch.
Drawn with MBP trackpad:
Hey thanks for sharing this!
Do you have a quick example code on how to add it to a fabric canvas?
Do you have a quick example code on how to add it to a fabric canvas?
I don't have code that I can share unfortunately, but the rough idea is:
BaseBrush
. You register the points and the pressure on onMouseMove
_render
to create an SVG path from the points, using perfect-freehand
Have a look at PencilBrush
, it's already very close to what you need to implement. The main difference is the PencilBrush
will transform the points into a smoothed path only at the finalization stage (on mouseup), whereas you probably want to render using the perfect-freeform
path both during drawing and on finalization.
I am for making this supported
Do you have a quick example code on how to add it to a fabric canvas?
I don't have code that I can share unfortunately, but the rough idea is:
Extend or hook into
BaseBrush
. You register the points and the pressure ononMouseMove
Override
_render
to create an SVG path from the points, usingperfect-freehand
Have a look at
PencilBrush
, it's already very close to what you need to implement. The main difference is thePencilBrush
will transform the points into a smoothed path only at the finalization stage (on mouseup), whereas you probably want to render using theperfect-freeform
path both during drawing and on finalization.
Thank you for you help! I will give it a try
+1 on adding first party support for this feature :)
Yep would also appreciate this :-)
This is really interesting, thanks a lot for sharing. The more I play with it the more I like it. Here is another one, although after playing with both extensively I think the perfect freehand works better across stroke widths.
Here is my pretty hacky attempt to integrate an override for the PencilBrush with the perfect freehand points. I used the simplify-js tool, and override _render and _finalizeAndAddPath. I'm sure it could be improved, and I don't add pressure to the Mouse event but I don't think it would be very hard. The Codepen is here
I'd be delighted to hear any suggestions.
Probably we could me a demo/tutorial on a custom brush. I absolutely have no pencil, otherwise i could test it. Does the trackpad support pressure by chance?
A tutorial would be great! I have a wacom so if a tutorial materialized I could test.
I just tried the simplest method I could think of in v5 which didn't work for me:
I attached a pointermove listener to the parent div of the canvas elements ( the pointerevents boolean on Canvas doesn't seem to do anything, and there aren't any listeners like 'pointer:move' for pointer events using Fabric's Canvas.on() . There should be a simpler way of hooking into the standard listeners rather than this custom string I think
I set the brush width according to pressure on mouse move.
The whole stroke changes width and it causes bugs for example with eraser, so I guess I'm misunderstanding how everything fits together...
MIne doesn't use the pressure from the mouse or touch event yet, but I'll work on that in the next couple of weeks. The drawing is beautiful. In the app I'm working on I built a settings control group where you can adjust the same things as the freehand demo - and I've compared them closely, and you can achieve very close to what he has in his demo. Not quite as buttery smooth, but I've tried using my Huion stylus which is high end (desktop), as well as an Android stylus on a Fire Max, as well as my finger and a kid type crayon stylus on my iPhone. I'm sure my implementation could be cleaned up but I'm really delighted with the results.
Is there currently any support for (or are there any plans to add) pressure / tilt from pens (e.g. Wacom tablet, iPad pencil, etc)? Pressure is typically used to vary the brush width as you are using the brush, so this would be the natural usecase for it. I've seen this done in a number of places (e.g. photoshop and most standalone painting tools), but below are some web-based examples that do it. These use the Pointer Events API, which does provide pressure info, as far as I can see.
https://aggie.io (tested that brush thickness based on pressure works with ipad + pencil) https://github.com/kanreisa/reichat (Microsoft Edge/windows only it seems?) https://github.com/thenickdude/chickenpaint/ (couldn't find working online demo, but code is there) And I'm sure there are others...
There's also https://github.com/stuyam/pressure which is a popular abstraction for getting pressure info, though I'm not sure why it's necessary these days thanks to the Pointer Events API.