diff --git a/src/content/docs/core-concepts.md b/src/content/docs/core-concepts.md new file mode 100644 index 00000000..f7e064ce --- /dev/null +++ b/src/content/docs/core-concepts.md @@ -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 { + ... + } +} + +``` diff --git a/src/content/docs/getting-started/index.md b/src/content/docs/getting-started/index.md index b6bd7345..12ab612c 100644 --- a/src/content/docs/getting-started/index.md +++ b/src/content/docs/getting-started/index.md @@ -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 - + ``` -### 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 diff --git a/src/content/docs/understanding-fabricjs/transformations.md b/src/content/docs/understanding-fabricjs/transformations.md new file mode 100644 index 00000000..785d37fe --- /dev/null +++ b/src/content/docs/understanding-fabricjs/transformations.md @@ -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