All Projects → jakubfiala → Atrament.js

jakubfiala / Atrament.js

Licence: other
A small JS library for beautiful drawing and handwriting on the HTML Canvas.

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Atrament.js

Ragg
Graphic Devices Based on AGG
Stars: ✭ 127 (-87.85%)
Mutual labels:  graphics, drawing
Gfx
Convenience package for dealing with graphics in my pixel drawing experiments.
Stars: ✭ 82 (-92.15%)
Mutual labels:  graphics, drawing
Perfect Freehand
Draw perfect pressure-sensitive freehand strokes.
Stars: ✭ 999 (-4.4%)
Mutual labels:  graphics, drawing
Imagesharp
📷 A modern, cross-platform, 2D Graphics library for .NET
Stars: ✭ 5,186 (+396.27%)
Mutual labels:  graphics, drawing
Luxor.jl
Simple drawings using vector graphics; Cairo "for tourists!"
Stars: ✭ 293 (-71.96%)
Mutual labels:  graphics, drawing
Godot Texture Painter
A GPU-accelerated texture painter written in Godot 3.0
Stars: ✭ 155 (-85.17%)
Mutual labels:  graphics, drawing
Graphicsrenderer
A drop-in UIGraphicsRenderer port -- CrossPlatform, Swift 4, Image & PDF
Stars: ✭ 85 (-91.87%)
Mutual labels:  graphics, drawing
Sketch
Sketch have a lot of basic functions to develop a drawing app for iPhone. Anyone can easily create drawing iOS Application.
Stars: ✭ 229 (-78.09%)
Mutual labels:  graphics, drawing
Openvg
Tools for exploring OpenVG
Stars: ✭ 371 (-64.5%)
Mutual labels:  graphics, drawing
Macaw
Powerful and easy-to-use vector graphics Swift library with SVG support
Stars: ✭ 5,756 (+450.81%)
Mutual labels:  graphics, drawing
Cml1
The Configurable Math Library, v1
Stars: ✭ 35 (-96.65%)
Mutual labels:  graphics
Ashengine
A cross-platform 3D engine based on Qt 5.9.7, OpenGL 3.3 and Assimp 4.1.
Stars: ✭ 35 (-96.65%)
Mutual labels:  graphics
Picasso
Homebrew PICA200 shader assembler
Stars: ✭ 41 (-96.08%)
Mutual labels:  graphics
Pencil
Pencil2D is an easy, intuitive tool to make 2D hand-drawn animations. Pencil2D is open source and cross-platform.
Stars: ✭ 968 (-7.37%)
Mutual labels:  drawing
Monogame
One framework for creating powerful cross-platform games.
Stars: ✭ 8,014 (+666.89%)
Mutual labels:  graphics
Jglm
Java OpenGL Mathematics Library
Stars: ✭ 44 (-95.79%)
Mutual labels:  graphics
Vktk
Vulkan Toolkit
Stars: ✭ 32 (-96.94%)
Mutual labels:  graphics
Purge Wrangler
AMD & NVIDIA eGPUs for all Thunderbolt Macs.
Stars: ✭ 960 (-8.13%)
Mutual labels:  graphics
Galeri Www
A perpetual artwork streaming app. (Website Repo)
Stars: ✭ 46 (-95.6%)
Mutual labels:  drawing
Shaderworkshop
Interactive GLSL fragment shaders editor made with Qt
Stars: ✭ 43 (-95.89%)
Mutual labels:  graphics

Atrament

A small JS library for beautiful drawing and handwriting on the HTML Canvas


Build Status

Atrament is a library that enables the user to draw smooth, natural drawings and handwriting on the HTML canvas. The algorithm was originally developed about 2 weeks after I started learning JavaScript, as I wanted to build a collaborative drawing space on the web, which ended up being 1WALL. I wanted the drawing to feel natural and comfortable, and the result to be smooth and pleasing. Years later, I've taken the algorithm, improved it, rewrote it in ES6 and made it into a neat little library.

FEATURES:

  • Draw/Fill/Erase modes
  • Adjustable adaptive smoothing
  • Events tracking the drawing - this allows the app to "replay" or reconstruct the drawing, e.g. for undo functionality
  • Adjustable line thickness and colour

Here's a basic demo.

Enjoy!

Installation

as a module

If you're using a tool like webpack or browserify to bundle your code, you can install it using npm.

  • install atrament as a dependency using npm install --save atrament.
  • You can access the Atrament class using const Atrament = require('atrament');

script tag

Include the script located at dist/atrament.min.js in the <head> tag of your HTML.

Alternatively, you can use Bower: bower install atrament and include bower_components/atrament/dist/atrament.min.js as a script tag.

polymer

Thanks to rubenstolk, you can also use the sc-atrament Polymer element.

Usage

  • create a <canvas> tag, e.g.:
<canvas id="sketchpad" width="500" height="500"></canvas>
  • in your JavaScript, create an Atrament instance passing it your canvas object:
const canvas = document.querySelector('#sketchpad');
const sketchpad = new Atrament(canvas);
  • you can also pass the width, height and default colour to the constructor:
const sketchpad = new Atrament(canvas, {
  width: 500,
  height: 500,
  color: 'orange',
});
  • that's it, happy drawing!

Options & config

  • clear the canvas:
sketchpad.clear();
  • change the line thickness:
sketchpad.weight = 20; //in pixels
  • change the color:
sketchpad.color = '#ff485e'; //just like CSS
  • toggle between modes:
sketchpad.mode = 'erase'; // eraser tool
sketchpad.mode = 'fill'; // click to fill area
sketchpad.mode = 'draw'; // default
sketchpad.mode = 'disabled'; // no modification to the canvas (will still fire stroke events)
  • tweak smoothing - higher values make the drawings look much better, lower values make drawing feel a bit more responsive. Set to 0.85 by default.
sketchpad.smoothing = 1.3;
  • toggle adaptive stroke, i.e. line width changing based on drawing speed for a more natural effect. true by default.
sketchpad.adaptiveStroke = false;
  • record stroke data (enables the strokerecorded event). false by default.
sketchpad.recordStrokes = true;
  • export as image:
//we have to get the dataURL of the image
const dataURL = sketchpad.toImage();
//then we can, for instance, open a new window with it
window.open(dataURL);

Events

Dirty/clean

These events fire when the canvas is first drawn on, and when it's cleared. The state is stored in the isDirty property.

sketchpad.addEventListener('dirty', () => console.info(sketchpad.isDirty));
sketchpad.addEventListener('clean', () => console.info(sketchpad.isDirty));

Stroke start/end

These events don't provide any data - they just inform that a stroke has started/finished.

sketchpad.addEventListener('strokestart', () => console.info('strokestart'));
sketchpad.addEventListener('strokeend', () => console.info('strokeend'));

Fill start/end

These only fire in fill mode. The fillstart event also contains x and y properties denoting the starting point of the fill operation (where the user has clicked).

sketchpad.addEventListener('fillstart', ({ x, y }) =>
  console.info(`fillstart ${x} ${y}`),
);
sketchpad.addEventListener('fillend', () => console.info('fillend'));

Stroke recording

Fires at the same time as strokeend and contains data necessary for reconstructing the stroke.

sketchpad.addEventListener('strokerecorded', ({ stroke }) =>
  console.info(stroke),
);
/*
{
  points: Array<Point>,
  color,
  weight,
  smoothing,
  adaptiveStroke,
}
*/

Programmatic drawing

To enable functionality such as undo/redo, stroke post-processing, and SVG export in apps using Atrament, the library can be configured to record the "pen strokes".

The first step is to enable recordStrokes, and add a listener for the strokerecorded event:

atrament.recordStrokes = true;
atrament.addEventListener('strokerecorded', ({ stroke }) => {
  // store `stroke` somewhere
});

The stroke can then be reconstructed using methods of the Atrament class:

// set drawing options
atrament.mode = stroke.mode;
atrament.weight = stroke.weight;
atrament.smoothing = stroke.smoothing;
atrament.color = stroke.color;
atrament.adaptiveStroke = stroke.adaptiveStroke;

// don't want to modify original data
const points = stroke.points.slice();

const firstPoint = points.shift();
// beginStroke moves the "pen" to the given position and starts the path
atrament.beginStroke(firstPoint.x, firstPoint.y);

let prevPoint = firstPoint;
while (points.length > 0) {
  const point = points.shift();

  // the `draw` method accepts the current real coordinates
  // (i. e. actual cursor position), and the previous processed (filtered)
  // position. It returns an object with the current processed position.
  const { x, y } = atrament.draw(point.x, point.y, prevPoint.x, prevPoint.y);

  // the processed position is the one where the line is actually drawn to
  // so we have to store it and pass it to `draw` in the next step
  prevPoint = { x, y };
}

// endStroke closes the path
atrament.endStroke(prevPoint.x, prevPoint.y);

Development

To obtain the dependencies, cd into the atrament directory and run npm install. You should be able to then build atrament by simply running npm run build.

I didn't bother writing tests because it's such a small package. Contributions are welcome!

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].