Security News
Node.js EOL Versions CVE Dubbed the "Worst CVE of the Year" by Security Experts
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.
@britannica/pablito
Advanced tools
An HTML 5 drawing tool based largely off existing tools.
This package makes use of fabricjs-webpack and Canvas-Drawing-Tool. It now uses Webpack 4, and imports, no more scripts in the header. This was easier than forking the original tool and updating the tooling. Please note that a large portion of this read-me is taken directly from the Canvas-Drawing-Tool repository.
npm install --save @britannica/pablito
To create a pablito drawing, you'll first need to include the script on the page:
In your javascript source import the library into your project:
import Pablito from '@britannica/pablito';
const container = document.getElementById('stickerbook-container');
document.body.appendChild(container);
const pablito = new Pablito({
// The containing element for the stickerbook
container : container,
// sticker configuration
stickers: {
// the available stickers that can be used
enabled: [
'path/to/first/image.png',
'path/to/other/image.png'
],
// styling options for sticker sizing controls (optional)
controls: {
cornerColor: 'rgba(0,0,0,0.5)',
cornerSize: 20,
hasBorders: true
},
// default positioning for stickers (provide whatever you need, the rest defaults to reasonable values)
defaults: {
x: 0, // if x and y defaults are not provided, you *must* provide them when calling placeSticker()
y: 0,
xScale: 1,
yScale: 1,
rotation: 0 // degrees
}
},
background: {
// the backgrounds that can be set
enabled: [
'first/bg.png',
'other/bg.png'
],
// the default background to use (can be null for empty background)
default: 'first/bg.png'
},
brush: {
// The available brushes. The list below has the all the currently available ones (at the time of writing)
enabled: [
'eraser',
'bitmap',
'bitmap-eraser',
'fill',
'marker',
'pattern',
'pencil',
'spray',
// a custom brush configured below
'mycustombrush'
],
// The available brush widths (in pixels)
widths: [1, 10],
// The available colors to use, can be any valid CSS color
colors: [
'#0000FF',
'#FF0000'
],
// any custom brushes, the key of this object are the id to be used in the enabled list above, and the value must
// be a subclass of fabric.BaseBrush (via fabric.util.createClass(fabric.BaseBrush, { }) )
custom: {
mycustombrush: MyCustomBrush
}
},
// Whether or not to enable touch events
mobileEnabled: true,
// Whether or not to use default event handlers (see "Events" below)
useDefaultEventHandlers: true
});
Note that the canvas fits to fill the containing element, so any height and width rules you've set will apply to the canvases inside. We advocate that you use viewport units to maintain aspect ratio, so that scaling preserves sizes properly. We'll loosen that suggestion as we improve our resizing algorithm. However, in the meantime the demo code stylesheet has an example of how to do this.
You can always re-render the stickerbook by hand using the triggerRender
method. This will simply call the internal
fabric instance's renderAll
. However, if you'd like to not only re-render but also want to recalculate positioning
(due to a change in the container size etc.), you can call resize
which will recalculate positioning for each canvas
element and then redraw.
Any operation that was previously done can be undone (or redone) via the undo
and redo
method respectively:
// do some stuff
pablito.undo();
// oh wait, I wanted to keep that! Give it back!
pablito.redo();
// bloodPressure--;
Brushes, stickers, and the background can all be set on the fly. Keep in mind that they are validated when set, so if you attempt to set a brush/sticker/background that is not enabled, an Error will be thrown. Here's an example:
pablito.setSticker('some/enabled/sticker.png');
pablito.setBrush('pencil');
pablito.setBrushWidth(10);
pablito.setBackground('some/enabled/bg.png');
try {
// this color is not enabled
pablito.setColor('PapayaWhip');
} catch(e) {
alert('ORLY?');
}
Note that pablito.setSticker
is ansynchronous due to the fact the browser will have to load the image before it
can add it to the canvas. Therefore, pablito.setSticker
returns a promise that resolves to the pablito once
the image has loaded.
Along with setting the background, you can remove it too:
pablito.clearBackground();
You can also programmatically unselect any UI items with
pablito.deselectAll();
When setting a brush via setBrush
, some brushes allow for configuration to be provided for that brush.
The bitmap brush takes an image and turns it into a "stamp" by replacing it's RGB channels with the color you specify. It preserves the alpha channel however, so you can use that shape the stamp in any way you want. Here's an example usage:
pablito.setBrush('bitmap', {
image: 'pathToSomeImage' // the image to sample
});
However, don't forget to enable this brush!
The bitmap eraser behaves exactly like the bitmap brush, but works as an eraser instead:
pablito.setBrush('bitmap-eraser', {
image: 'pathToSomeImage' // the image to sample
});
The pattern brush takes an array of images and stamps them as the user drags their mouse/finger across the canvas. Here is an example configuration:
pablito.setBrush('pattern', {
images: [
'image1',
'image2'
]
})
The fill brush allows you to configure some of its behavior. Since the fill algorithm is computationally expensive, in some circumstances it's better to spread the fill algorithm's intermediate work over multiple frames. This has the benefits of:
By default, the fill tool is configured to do all the work on a single frame. For a smaller canvas, or on desktop, this may be sufficient. This is the default behavior:
pablito.setBrush('fill');
There is, however a way to spread this work over multiple frames. Consider the following configuration:
pablito.setBrush('fill', {
isAsync: true,
stepsPerFrame: 10,
partialFill: false
});
In this case the fill tool will animate it's progress, but stop animating when you mouse up or touch end (the default behavior). This means
that the filled region might not be completely finished, but stopped on the end of user interaction. Moreover, the algorithm
will attempt to fill 10 scanlines per frame (the default if don't provide stepsPerFrame
configuration).
Now, consider this other configuration:
pablito.setBrush('fill', {
isAsync: true,
stepsPerFrame: 10,
partialFill: true
});
In this case the fill tool will animate it's progress, and keep going even when the user mouses up (or touch end). The image will be added whenever the algorithm finishes.
You can also export the pablito to a data url for saving, printing, whatever like so:
var dataUrl = pablito.toDataURL();
// now, go hog-wild
// courtesy of http://stackoverflow.com/a/2909070
var html = "<!DOCTYPE html>\n<html><body><img src=\"" + dataUrl + "\"/></body></html>";
var popup = window.open();
popup.document.write(html);
popup.focus();
popup.print();
The above example will attempt to print the image. You can download and save to camera roll with even less code:
window.location.href = pablito.toDataURL().replace("image/png", "image/octet-stream");
Bear in mind that this the internal toDataURL()
call we make to the canvas element will fail if any sticker
placed on the canvas came from a different origin (perhaps a CDN or the like). This can alleviated by setting the
proper Access-Control-Allow-Origin
header on the resource to allow it to be used freely by your page.
The pablito provides background positioning methods, so you can adjust how the background looks as your canvas scales and grows. There are three options (currently):
pablito.backgroundManager.setPositioning('default');
pablito.backgroundManager.setPositioning('fit-height');
pablito.backgroundManager.setPositioning('fit-width');
default
is the default behavior, and simply positions the image in the top corner with no scaling at all.
fit-height
will scale the image so that it is as tall as the canvas and centered horizontally. fit-width
is the
opposite and fills the image horizontally, while centering it vertically. If an unknown option is provided for
positioning, the default will be used.
You can also provide positioning that fits once, but never scales again (after a canvas resize for instance):
fit-width-no-rescale
and fit-height-no-rescale
will acheive this. This are helpful for maintaining the background
image's position relative to the position of the drawings on the canvas.
A pablito instance fires events from the underlying Fabric canvas, and you can register custom callbacks to respond to them using the on
and off
methods.
If you configure the pablito with useDefaultEventHandlers: true
, it will register built-in event handlers for manipulating stickers with mouse and touch events. With useDefaultEventHandlers: true
, those handlers won't be registered. See event-handlers.js
for the source code of the default handlers.
You can register callbacks for the following events:
'before:selection:cleared',
'mouse:down',
'mouse:move',
'mouse:out',
'mouse:over',
'mouse:up',
'object:modified',
'object:moving',
'object:rotating',
'object:scaling',
'object:selected',
'path:created',
'selection:cleared',
'selection:created',
'touch:drag',
'touch:gesture',
'touch:longpress',
'touch:orientation',
'touch:shake'
pablito.on('touch:longpress', function handleLongPress(evt) {
// custom logic...
});
You can also de-register event handlers
const handleLongPress = function (evt) {
// custom logic...
};
pablito.on('touch:longpress', handleLongPress);
// later, we want to remove this handler
pablito.off('touch:longpress', handleLongPress);
It's possible to manipulate stickers directly, for example in custom event handlers:
pablito.getTopSticker().setAngle(90);
pablito.triggerRender();
Remember to call triggerRender()
to make your manipulations visible.
low-level sticker API is from fabric:
http://fabricjs.com/docs/fabric.Object.html
Example methods:
sticker.setAngle()
(http://fabricjs.com/docs/fabric.Object.html#setAngle)
sticker.scale()
(http://fabricjs.com/docs/fabric.Object.html#scale)
If you have called pablito.setSticker
with some url, you can place the image programmatically as well. By calling
pablito.placeSticker({ x: 0, y: 0 })
you can place an image manually onto the canvas. You can also provide an
optional xScale
, yScale
and rotation
to place the image in a particular starting layout.
If you're done with the pablito, you can simply call pablito.destroy()
to remove any DOM
nodes, listeners, memory added by the pablito. However, it will not remove the container you
provide. Please note that when you call destroy
, the pablito is no longer usable and any
method call is then considered undefined behavior.
npm start
Live reloading is available for the package, however the demo will need to be refreshed if you make a change.
FAQs
Pablito An HTML 5 drawing library that leverages FabricJS for the majority of the features.
The npm package @britannica/pablito receives a total of 8 weekly downloads. As such, @britannica/pablito popularity was classified as not popular.
We found that @britannica/pablito demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.
Security News
cURL and Go security teams are publicly rejecting CVSS as flawed for assessing vulnerabilities and are calling for more accurate, context-aware approaches.
Security News
Bun 1.2 enhances its JavaScript runtime with 90% Node.js compatibility, built-in S3 and Postgres support, HTML Imports, and faster, cloud-first performance.