Skip to content

Commit

Permalink
docs(): tweak installation + core concepts (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
ShaMan123 authored Aug 19, 2023
1 parent 5b08b8e commit 3c71864
Show file tree
Hide file tree
Showing 3 changed files with 267 additions and 8 deletions.
175 changes: 175 additions & 0 deletions src/content/docs/core-concepts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
---
date: '2023-08-20'
title: 'Core Concepts'
description: 'Core Concepts'
---

# Core Concepts

## State

State is comprised of 2 aspects. The **logical** state and the **visual** state.
The **visual** state is our end game, what the user sees, whereas the **logical** state is what exists under the hood.
The 2 are deeply intertwined. However, in many cases, looking at a problem with this concept in mind produces much simpler and performant solutions.

Caching and erasing are 2 examples that utilize this concept.

_Cheating_ the user to think something is happening by showing a visual outcome (that may not correlate to the **logical** state) is sometimes the best way to solve a problem.

Since we are dealing with 2 states there are cases they fall out of sync.
Flagging an object as `dirty` will sync its visual state on the next render (invalidating its cache, if it is caching).

```ts
object.set({ dirty: true });
```

Syncing its **logical** state is needed for user interactions.

```ts
object.setCoords();
```

## Objects

Objects are shapes with a lifecycle that supports both the **logical** and the **visual** states.

- `Path`
- `Polyline`, `Polygon`
- `Rect`
- `Circle`, `Ellipse`
- `Image`
- `Text`, `IText`, `Textbox`

## Interactions

User interactions drive both **logical** and **visual** state changes.
The standard fabric app is built mainly on interactions.
As such there are many **events** to subscribe to in order to make it easier to achieve complex UX.

```ts
object.on('eventName', ...);
```

### Selection

Fabric supports the following selection modes out of the box:

- Single object selection
- Area selection
- Multi selection

### Controls

Performing state changes on an object is done using its controls.
Fabric exposes the following controls:

- scaling
- rotating
- resizing
- skewing
- translating action

The `Control` API is designed especially for creating custom controls and customizing existing ones.

### Drawing & Brushes

The drawing interaction is controlled by `Canvas#freeDrawingBrush` and `Canvas#isDrawingMode`.
Once the interaction completes an object is created => listen to the `path:created` event for it.

Available brushes:

- `CircleBrush`
- `PatternBrush`
- `PencilBrush`
- `SprayBrush`

### Zoom, Pan & Viewport interactions

Fabric doesn't support these interaction out of the box.
Check out the demo.

### Animations

Animations are another form of state change.
It is possible to animate anything in fabric as long as you sync the state properly.
Remember to cleanup after yourself by aborting running animations.

## Visual State

### Rendering

Rendering is the process in which a canvas or an object redraws itself.
By doing so it syncs the **visual** state.

Keep in mind that rendering can be expensive and therefore can lead to a drop in performance.

Rendering is performed in the parent plane, see [transformations](#transformations).

Objects need a reference to canvas for proper rendering (handled by fabric under the hood).

#### `renderAll` vs. `requestRenderAll`

`renderAll` is sync, `requestRenderAll` is not, both render the canvas.
`requestRenderAll` first request an animation frame before rendering.
Calling `requestRenderAll` repeatedly will have no effect as long as rendering has not started.

### Caching

Caching means rendering an object onto a standalone canvas (called a cache). Then, when rendering occurs we can pull the cache and render it instead of redrawing the object.

Caching is used for 2 reasons:

- Performance\
We save on redrawing the object if its state did not change.

- Context Isolation\
Performing complex rendering such as clipping, filtering, using `globalCompositeOperation` etc. need an isolated context to render on in order for the operation to remain isolated and not to affect the entire canvas, so we use the cache.

## I/O

Fabric supports `JSON` and `SVG` serialization.
Take a look at:

| | In | Out |
| ---------- | ------------- | --------------- |
| **`JSON`** | `fromObject` | `toObject` |
| **`SVG`** | `fromElement` | `toSVG` |
| **`PDF`** | `N/A` | Use node canvas |

Use the `classRegistry` to register your own classes for parsing.

If you encounter issues with serialization try changing `NUM_FRACTION_DIGITS`.

## Customization, Subclassing & Mutation

```ts
// subclass
class MyRect extends Rect {

// override methods
...

// override default values
getDefaults() {
return {
...super.getDefaults(),
...
}
}
}
// register subclass for I/O
classRegistry.setClass(MyRect);

// prototype mutation
fabric.Object.prototype.someMethod = function() {
...
}

// override default values
fabric.Object.getDefaults = function() {
return {
...
}
}

```
15 changes: 7 additions & 8 deletions src/content/docs/getting-started/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,27 @@ title: 'Getting started'
description: 'Getting started with FabricJS'
---

In this guide, we'll get started with the basics of FabricJS

## Installation

FabricJS can be made available via following approaches as suited by your project

### Installing from CDN via script tag
### Installing from CDN via script tag [![cdnjs](https://img.shields.io/cdnjs/v/fabric.js.svg)][cdnjs] [![jsdelivr](https://data.jsdelivr.com/v1/package/npm/fabric/badge)][jsdelivr]

Include a script tag within your HTML page

```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.min.js"></script>
<script src=https://cdn.jsdelivr.net/npm/fabric@latest/dist/index.js></script>
```

### Installing from Node registry

Install from NPM
### Installing from npm [![NPM](https://badge.fury.io/js/fabric.svg)](http://badge.fury.io/js/fabric)

```shell
npm install fabricjs
npm i --save fabric
```

## Browser support

Following is a table portraying what features are supported across particular browsers

[cdnjs]: https://cdnjs.com/libraries/fabric.js
[jsdelivr]: https://www.jsdelivr.com/package/npm/fabric
85 changes: 85 additions & 0 deletions src/content/docs/understanding-fabricjs/transformations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
date: '2023-08-20'
title: 'Transformations'
description: 'Transformations'
---

# Transformations

## Math Intro

A transformation is described by a matrix:

```ts
const matrix = [a, b, c, d, e, f];

const vectorX = [a, b];
const vectorY = [c, d];
const translation = [e, f];
```

`vectorX` and `vectorY` describe the transform applied to the unit vectors `[1, 0]` and `[0, 1]` respectively.
We use the decomposed values (`angle`, `scaleX`, `scaleY`, `skewX`, `skewY`) that are derived from the transformation applied to the unit vectors, see `qrDecompose`.

`translation` describes the offset from the parent plane's `(0, 0)` to the center of the plane, decomposed into `translateX` and `translateY`. Canvas `(0, 0)` is the canvas' tl corner, group `(0, 0)` is the group's center point.

Transformations application order:

- Translation
- Rotation
- Scale
- SkewX
- SkewY

Read more about [matrices] and [transforms] on MDN.

## How It Works

Each object has its own transform that defines a _plane_.
An object can exist in a _plane_ defined by another object (e.g. an object nested under a group, a clip path). This means that the object is affected by that _plane_.

Transformations application order:

- Viewport
- Parent groups
- Own

```ts
// own transform
object.calcOwnTransform();

// object transform including parent groups
object.calcTransformMatrix();

// the plane in which the object exists
multiplyTransformMatrixArray([canvas.viewportTransform, object.group?.calcTransformMatrix()]);
```

Using transformations can be tricky. Sometimes we need to use the relative parent plane (e.g. during rendering) whereas sometimes we need to use the canvas plane or the viewport plane (e.g. object intersection, mouse interactions).

Fabric exposes the following utils for such cases:

```
sendPointToPlane
sendVectorToPlane
sendObjectToPlane
```

### Origin

Positioning an object can be done from the center point or from any other point

```ts
// sets the center point in the canvas plane
object.setCenterPoint(point);
// sets the center point in the parent plane
object.setRelativeCenterPoint(point);

// sets the tl point in the canvas plane
object.setXY(point, 'left', 'top');
// sets the br point in the parent plane
object.setRelativeXY(point, 'bottom', 'right');
```

[transforms]: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations#transforms
[matrices]: https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Matrix_math_for_the_web

0 comments on commit 3c71864

Please sign in to comment.