Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@

### Added

- The `pressureSensitive` property (#136): the strokes of the pencil which a pen (a stylus) draws are as wide as
the pressure on it, read from `PointerEvent.pressure`. `lineWidth` is the width at a medium pressure, and a stroke
is between a tenth and twice of it. The strokes of a mouse and of a finger are drawn as before, and the canvas
still reads the mouse and the touches, so the pinch zoom is not changed. Such a stroke is a filled path, saved
as the type `PressureStroke` with the discs along it (a few kilobytes for a long stroke, where the commands of
the path would be a few hundred), one object and one undo step. The showcase has a Pen pressure switch for the pencil.
- `toDataURL({ multiplier: "original" })` (#75): the drawing at the resolution of the background image, one
pixel of the picture for each pixel of the image, at any size of the canvas. Without a background image the
multiplier is 1. An image which is scaled differently in the two directions is exported at the larger
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ All properties are optional.
| `lineColor` | `string` | `"black"` | Color of the line. |
| `lineWidth` | `number` | `10` | Width of the line. |
| `lineStyle` | `Types.LineStyle` | `"solid"` | Style of the line: `"solid"`, `"dashed"`, `"dotted"` or `"dash-dot"`. See [Line style](#line-style). |
| `pressureSensitive` | `boolean` | `false` | Draw the strokes of a pen (a stylus) with a width which follows its pressure. Only the pencil has it. See [Pen pressure](#pen-pressure). |
| `fillColor` | `string` | `"transparent"` | Fill color of the shapes, where applicable (rectangle, rectangle-label, circle). |
| `backgroundColor` | `string` | `"transparent"` | Background color of the sketch, in hex or rgba format. |
| `backgroundImage` | `string` | | URL or data URL of the background image. It is set when the component mounts and when it changes, and removed when it is gone. It takes the place of the background image of `value` and `defaultValue`. |
Expand Down Expand Up @@ -491,6 +492,28 @@ The line is drawn on the top canvas of fabric only, it is never an object of the
`toJSON()` or `toDataURL()`, it is not an undo step, `onObjectAdded` is not called for it, and `onChange` is
not called when it is drawn. Switching to another tool clears what is left of the line.

### Pen pressure

With `pressureSensitive`, the strokes of the pencil which a pen (a stylus) draws are as wide as the pressure on it:
`lineWidth` is the width at a medium pressure, a light pressure draws a thinner line (down to a tenth of it) and a
hard one a wider line (up to twice). A pen which reports a constant pressure draws a line of `lineWidth`.

```tsx
<SketchField tool="pencil" lineWidth={8} pressureSensitive />
```

- The pressure is read from the pointer events of the page (`PointerEvent.pressure` and `pointerType`), which come
before the mouse and the touch events the canvas draws with, so the mouse, the touches and the pinch zoom work as
before. The strokes of a mouse and of a finger are drawn as they are, as they have no pressure. It needs a browser
which sends pointer events for the pen, which the current ones do.
- A stroke is a filled path, the outline of the stroke, and not a line with a width: it is the type `PressureStroke`
in `toJSON()` (a path of fabric, with the discs along the stroke as `discs` and not the commands of the path,
which are twenty times as long), and it is loaded as one by `value`, `defaultValue` and `fromJSON()`. A version
without this cannot load it. It is one object and one undo step, which is selected, moved, scaled, erased and
copied as any path. The color is its `fill`.
- `lineStyle` does not apply to it (it has no dashes), and neither does the straight line of the shift key.
- The highlighter does not have it.

## Exports

| Export | Description |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { FabricCanvasTool } from "./tools";
import { create_tool } from "./tools/factory";
import { Eraser } from "./tools/Eraser";
import { Polygon } from "./tools/Polygon";
import { releasePen } from "./tools/PressureBrush";

/**
* The properties which always have a value, because SketchField provides
Expand Down Expand Up @@ -292,6 +293,7 @@ class SketchField extends PureComponent<SketchProperties & DefaultedProps> {
props.lineColor !== prevProps.lineColor ||
props.lineWidth !== prevProps.lineWidth ||
props.lineStyle !== prevProps.lineStyle ||
props.pressureSensitive !== prevProps.pressureSensitive ||
props.fillColor !== prevProps.fillColor
) {
this.configureTool();
Expand Down Expand Up @@ -324,6 +326,7 @@ class SketchField extends PureComponent<SketchProperties & DefaultedProps> {
this.tool.dispose();
// The canvas element is released at once, so it can be used again (React
// strict mode mounts twice). The rest is freed once the pending render is done.
releasePen(this.canvas);
void this.canvas.dispose();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export class Highlighter extends FabricCanvasTool {
this.canvas.isDrawingMode = true;
this.brush.width = props.lineWidth ? props.lineWidth : 1;
this.setBrushStroke(undefined, this.brush.width);
this.setPressureSensitive(false);
this.brush.color = hexToRgbA(
color.startsWith("#") ? color : (colorNameToHex(color) ?? color)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class Pencil extends FabricCanvasTool {
this.brush.width = config.lineWidth ? config.lineWidth : 1;
this.brush.color = config.lineColor ? config.lineColor : "black";
this.setBrushStroke(config.lineStyle, this.brush.width);
this.setPressureSensitive(config.pressureSensitive === true);
}

type(): Tool {
Expand Down
Loading
Loading