Introduction to the

First things first: This article is a long one, so I suggest you like it.

Fabric. The introduction of js

Fabric.js is a powerful and simple Javascript HTML5 Canvas library.

If you need to use canvas for special effects, I recommend using fabric.js because the syntax is easier to use and it also provides a lot of interactive apis.

Fabric.js simplifies a lot of Canvas concepts and makes the code look more semantic.


What can fabric.js do?

You can go to the “Fabric.js home page” to see examples directly, or you can check out the “fabric.js Demos” to see cooler examples.




In this article

If you are a 0-based reader, you want to be able to read from beginning to end and have at least a rough idea of what fabric.js does.


This article is based on my learning process, and if you follow it step-by-step, you’ll be able to get started with fabric.js, while improving your sleep quality and solving a lot of problems like excessive hair.


Since I have not been using fabric.js for a long time, this note will not be comprehensive or completely correct in each knowledge point. If you find any inaccuracies in this article, please feel free to point them out and I will correct them


This article is suitable for people:

  • Developers with a native three-piece base
  • It is better forcanvasBasic (this is a plus, it’s ok to have none at all)

This article focuses on the basics of fabric.js, including:

  • Basic operations on the canvas
  • Basic graph drawing methods (rectangle, circle, triangle, ellipse, polygon, line segment, etc.)
  • Use of images and filters
  • Text and text boxes
  • animation
  • Break up and break up
  • Base events
  • Free drawing
  • tailoring
  • Serialization and deserialization

In addition, we will talk about some more advanced operations, such as:

  • Custom action Angle style and state
  • Custom control
  • Copy and paste graphics
  • Manipulate graphs and groups using events

In addition to the above content, I will also sort out more common and fun operations according to the future work, this article is learning warehouse will be updated from time to time!!




A link to the

“Fabric.js NPM Address”

“Fabric.js Github Address”


🎁 Online preview of this case

🎁 All cases of this article warehouse address [welcome Star, not regularly updated!!]








Development environment setup

Environment and version description

  • The version of fabric.js used for this article is 4.6.

  • The development environment for this article is a Vue 3.2 project built using Vite.

If you don’t have Vite or Vue3.2, don’t be afraid, because Vite is really simple enough.

The purpose of this article is to explain fabric.js, so there is very little use for Vue 3.2, which I will explain in detail when I do.

If you don’t want to use Vite and Vue 3.2, that’s fine, just build your project the way you like.

Now just follow these steps to set up the project.


Build environment (Vite + Vue3)

Vite website

Vue3 website

Skip this section if you don’t want to use Vite + Vue3.

I also recommend that you use the native (HTML+CSS+JS) way to learn fabric.js, because it’s the fastest way to get started.


1. Build Vite project

npm init @vitejs/app
Copy the code


2. Give the project a name and select Vue

Then you’ll be asked to choose vUE or VUE + TS. I chose VUE, whatever you want.

Why not ts? Because ts is not worth the cost for a one-person training project.


3. Initialize the project

In fact, the previous step will give you a prompt (3 commands), then you can run the project

# go to the project directory CD fabric-demo # initialize project NPM install # Run project NPM run devCopy the code

If NPM is too slow, use CNPM.

If you don’t know how to do CNPM, please baidu yourself.


Installation of the Fabric. Js

Mode 1: CDN

<script src="https://unpkg.com/[email protected]/dist/fabric.min.js"></script>
Copy the code

You can use CDN for introduction, because it’s the fastest way to learn.

Method 2: NPM

This article uses this method!!

npm i fabric --save
Copy the code

When installed, package.json appears with the line of code pointed to by the arrow.








start

It only takes three operations to show something.

1. Create a page and import fabric.js

If it is a native project, use the

<script src="https://unpkg.com/[email protected]/dist/fabric.min.js"></script>
Copy the code

This article uses a Vite built project, so you can import it using import

import { fabric } from 'fabric'
Copy the code


2. Create a Canvas container

Create

in HTML and set the container ID and width, width/height

<canvas width="400" height="400" id="c" style="border: 1px solid #ccc;"></canvas>
Copy the code

Here we create a Canvas container with id=”c”.

Specify 400px and 400px, but note that there is no need to add px.

style=”border: 1px solid #ccc;” This sentence can be omitted, just to see where the canvas element is in the browser.


3. Use Fabric to take over the container and draw a rectangle

After you instantiate fabric in JS, you can use fabric’s API to manage the Canvas.

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric' / / into the fabric

function init() {
  const canvas = new fabric.Canvas('c') // The canvas ID is passed in here

  // Create a rectangle
  const rect = new fabric.Rect({
    top: 30.// 30px from the top of the container
    left: 30.// Distance 30px to the left of the container
    width: 100./ / 100 px wide
    height: 60./ / 60 px high
    fill: 'red' // Fill it with red
  })

  // Add rect to canvas canvas. I don't know what to add
  canvas.add(rect)
}

// The canvas element is not found until the page container is loaded.
// onMounted is a page lifecycle function provided by Vue3 that is called after the instance is mounted.
/ / onMounted official documentation: https://v3.cn.vuejs.org/guide/composition-api-lifecycle-hooks.html
onMounted(() = > {
  init() // Execute the initialization function
})
</script>
Copy the code

See the comments on each line of code for details.

Even if I don’t write a note, I can see that the code for fabric.js is very semantic, and I can probably guess the effect of the code by looking at the words.

If it is written using the native Canvas method, students who have not been familiar with it will not understand what is being written.








The canvas

The Fabric. Js canvas manipulation is very strong, here are a few common examples, other operations can be seen in the official documentation.

“Fabric.js Canvas Manipulation – Documentation”

🎁 Online preview of this section case – Canvas

🎁 This section code repository

Basic (interactive)

The basic edition is the example described in the “Getting Started” section.

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric' / / into the fabric

function init() {
  const canvas = new fabric.Canvas('canvas') // The canvas element id is passed in

  // Create a rectangle
  const rect = new fabric.Rect({
    top: 100.// Distance 100px from the top of the container
    left: 100.// Keep 100px to the left of the container
    width: 30.// Rectangle width 30px
    height: 30.// Rectangle height 30px
    fill: 'red' // Fill it with red
  })

  canvas.add(rect) // Add the rectangle to the canvas canvas
}

onMounted(() = > {
  init()
})
</script>
Copy the code


An interactive

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric' / / into the fabric

function init() {
  // Create an inoperable canvas using StaticCanvas
  const canvas = new fabric.StaticCanvas('canvas') // The canvas element id is passed in

  // Create a rectangle
  const rect = new fabric.Rect({
    top: 100.// Distance 100px from the top of the container
    left: 100.// Keep 100px to the left of the container
    width: 30.// Rectangle width 30px
    height: 30.// Rectangle height 30px
    fill: 'red' // Fill it with red
  })

  canvas.add(rect) // Add the rectangle to the canvas canvas
}

onMounted(() = > {
  init()
})
</script>
Copy the code

To create a non-interactive Canvas, simply change new fabric.canvas to new Fabric.staticcanvas.


Set canvas parameters in js

<template>
  <canvas id="canvas"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric' / / into the fabric

function init() {
  const canvas = new fabric.Canvas('canvas', {
    width: 300.// Canvas width
    height: 300.// Canvas height
    backgroundColor: '#eee' // Canvas background color
  })

  / / round
  const circle = new fabric.Circle({
    radius: 30.// Radius of the circle
    top: 20.// Distance 20px from the top of the container
    left: 20.// Distance 20px to the left of the container
    fill: 'pink' // Fill it with pink
  })
  
  canvas.add(circle) // Add the circle to the canvas canvas
}

onMounted(() = > {
  init()
})
</script>
Copy the code

The second parameter to new fabric.canvas is used to set the Canvas base functionality. For more configuration parameters, see “Official Documentation”.


Use background images

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  // Set the background image
  // Parameter 1: Background map resource (can be imported locally, can also use network map)
  // Parameter 2: After setting the background image, perform the following operations to re-render the canvas so that the background image is displayed
  canvas.setBackgroundImage(
    'https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/27d1b4e5f8824198b6d51a2b1c2d0d75~tplv-k3u1fbpfcp-zoom-crop-mark:400:4 00:400:400.awebp',
    canvas.renderAll.bind(canvas)
  )
}

onMounted(() = > {
  init()
})
</script>
Copy the code

SetBackgroundImage which is pretty easy to understand, set the background image.

Note that using giFs in fabric.js only renders the first frame.


Rotating background

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  // Set the background image
  // Parameter 1: Background map resource (can be imported locally, can also use network map)
  // Parameter 2: After setting the background image, perform the following operations to re-render the canvas so that the background image is displayed
  canvas.setBackgroundImage(
    'https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/27d1b4e5f8824198b6d51a2b1c2d0d75~tplv-k3u1fbpfcp-zoom-crop-mark:400:4 00:400:400.awebp',
    canvas.renderAll.bind(canvas),
    {
      angle: 15 // Rotate the background image
    }
  )
}

onMounted(() = > {
  init()
})
</script>
Copy the code

SetBackgroundImage has a third parameter, heh heh heh

The third parameter, in addition to rotation, can also set scaleX, scaleY, and so on.

See Documentation for more Settings.


One problem with this example is that if the size of the image is smaller than the canvas container, it will not fill, otherwise it will overflow (only part of the image will be displayed).

For the solution, see the next case.


Stretching background

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  // fabric.image. fromURL: API for loading images
  // First parameter: image address (can be local or network graph)
  // The second argument: the image load callback function
  fabric.Image.fromURL(
    'https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/27d1b4e5f8824198b6d51a2b1c2d0d75~tplv-k3u1fbpfcp-zoom-crop-mark:400:4 00:400:400.awebp'.(img) = > {
      // Set the background image
      canvas.setBackgroundImage(
        img,
        canvas.renderAll.bind(canvas),
        {
          scaleX: canvas.width / img.width, // Calculate the width of the image to stretch
          scaleY: canvas.height / img.height // Calculate how far to stretch the image
        }
      )
    }
  )
}

onMounted(() = > {
  init()
})
</script>
Copy the code

This example uses the fabric.image. fromURL API to load the Image. The first argument is the Image address and the second argument is the callback function.

Take the parameters of the image and calculate the width and height of the canvas so that the image fills the full screen.


Repeated background

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  canvas.setBackgroundColor({
    source: 'https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/27d1b4e5f8824198b6d51a2b1c2d0d75~tplv-k3u1fbpfcp-zoom-crop-mark:40:40 :40:40.awebp'.repeat: 'repeat'
  }, canvas.renderAll.bind(canvas))
}

onMounted(() = > {
  init()
})
</script>
Copy the code

The image size used in this example is relatively small, so in the third parameter of setBackgroundColor we set repeat: ‘repeat’ to repeat the image.


Overlapping image

<template>
  <canvas width="400" height="375" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'
import jailCellBars from '@/assets/images/jail_cell_bars.png' // Introduce the background image

function init() {
  const canvas = new fabric.Canvas('canvas')

  canvas.add(
    new fabric.Circle({
      radius: 30.// Circle radius
      fill: '#f55'.top: 70.left: 70}))// Sets the canvas to overlay the image
  canvas.setOverlayImage( // setOverlayImage(image, callback, optionsopt)
    jailCellBars, // picture, script start import in
    canvas.renderAll.bind(canvas)
  )
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Two things to note:

  1. usecanvas.setOverlayImageIn lieu ofcanvas.setBackgroundImage
  2. It is best to use images with transparent layerspngThis will show the effect shown in the example, with the background image superimposed on top of the graphic elements.

🎁 The address of the image used in this example








Basic shapes

Fabric.js provides the following basic graphics:

  • “Rectangle”
  • “Circular”
  • “Oval”
  • “Triangle”
  • “Line”
  • “Line”
  • “Polygon”


🎁 Online preview of this section case – Basic graphics

🎁 This section code repository

rectangular

<template>
  <canvas width="400" height="375" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas') // Bind canvas and pass in id

  const rect = new fabric.Rect({
    top: 100.// Distance 100px from the top of the container
    left: 100.// Keep 100px to the left of the container
    fill: 'orange'.// Fill with orange
    width: 100./ / width 100 px
    height: 100 / / height 100 px
  })
  
  // Add the rectangle to the canvas
  canvas.add(rect)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Create the rectangle using new fabric.rect.


The rounded rectangle

<template>
  <canvas width="400" height="375" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas') // Bind canvas and pass in id

  const rect = new fabric.Rect({
    top: 100.// Distance 100px from the top of the container
    left: 100.// Keep 100px to the left of the container
    fill: 'orange'.// Fill with orange
    width: 100./ / width 100 px
    height: 100./ / height 100 px
    rx: 20.// The X-axis radius
    ry: 20 // The y radius
  })
  
  // Add the rectangle to the canvas
  canvas.add(rect)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

To draw a rounded rectangle, you need to add Rx and RY. The values of these two attributes can be different. If you know the principle of CSS rounded corners, it is not difficult to understand Rx and RY.

So if you modify these two values and see what they look like it’ll make a lot of sense.


circular

<template>
  <canvas width="400" height="375" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const circle = new fabric.Circle({
    top: 100.left: 100.radius: 50.// The radius of the circle is 50
    fill: 'green'
  })
  canvas.add(circle)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Create a Circle using new fabric.circle.

For circles, use RADIUS to set the radius.


The oval

<template>
  <canvas width="400" height="375" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const ellipse = new fabric.Ellipse({
    top: 20.left: 20.rx: 70.ry: 30.fill: 'hotpink'
  })
  canvas.add(ellipse)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Ellipse needs to be created using new Fabric. Ellipse.

Unlike circles, ellipses do not require RADIUS, but rx and RY.

  • whenrx > ryAn ellipse is horizontal
  • whenrx < ry: An ellipse is vertical
  • whenrx = ry: It looks like a circle


triangle

<template>
  <canvas width="400" height="375" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const triangle = new fabric.Triangle({
    top: 100.left: 100.width: 80.// The bottom length
    height: 100.// The distance from base to diagonal
    fill: 'blue'
  })
  canvas.add(triangle)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

usenew fabric.TriangleCreate a triangle that requires a “base and height”.


Line segment

<template>
  <canvas width="400" height="375" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const line = new fabric.Line(
    [
      10.10.// Start point coordinates
      200.300 // End point coordinates] and {stroke: 'red'.// Stroke color
    }
  )
  canvas.add(line)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Create a Line segment using new fabric.line.

New fabric.line requires two arguments.

  • The first parameter is an array, which requires passing four values. The first two values are the x and y of the starting coordinate, and the last two values are the x and y of the ending coordinate.

  • The second argument is the style of the line segment. To set the color of the line segment, use stroke.


Broken line

<template>
  <canvas width="400" height="375" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const polyline = new fabric.Polyline([
    {x: 30.y: 30},
    {x: 150.y: 140},
    {x: 240.y: 150},
    {x: 100.y: 30}, {fill: 'transparent'.// If you draw a broken line, fill it with transparency
    stroke: '#6639a6'.// Line segment color: purple
    strokeWidth: 5 // Line segment thickness 5
  })
  canvas.add(polyline)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Create a line segment using new fabric.polyline.

New fabric.Polyline requires passing in two parameters.

  • The first argument is an array that describes each point of the line segment
  • The second parameter describes the line segment style

It should be noted that only when fill is set to transparent will line segments be displayed. Otherwise, black will be filled by default, as shown below:

You can also fill in any color you like. New Fabric. Polyline does not automatically close the start and end points.


polygon

<template>
  <canvas width="400" height="375" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const polygon = new fabric.Polygon([
    {x: 30.y: 30},
    {x: 150.y: 140},
    {x: 240.y: 150},
    {x: 100.y: 30}, {fill: '#ffd3b6'./ / fill color
    stroke: '#6639a6'.// Line segment color: purple
    strokeWidth: 5 // Line segment thickness 5
  })
  canvas.add(polygon)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Polygon draws polygons using new Fabric. Polygon. The usage is similar to new Fabric. Polyline, but the main difference is that new Fabric. Polygon automatically connects the start and end points.








Draw the path

“Fabric.js Path Path – Document”

🎁 Preview the case online – Draw a path

🎁 This section code repository

<template>
  <canvas width="400" height="375" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  // Draw the path
  const path = new fabric.Path('M 0 0 L 200 100 L 170 200 z')
  path.set({
    top: 50.// Distance 50px from the top of the container
    left: 50.// Keep the container 50px to the left
    fill: 'hotpink'.// Fill with bright pink
    opacity: 0.5.// The opacity is 50%
    stroke: 'black'.// The stroke color is black
    strokeWidth: 10 // Stroke width 10px
  })
  canvas.add(path)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Create a Path using new fabric.Path.

  • M: Can be understood as the new starting point x, y coordinate
  • L: the x and y coordinates of each of these points
  • Z: Automatic closure (automatically connect the end point with the start point)








The text

Fabric.js has three classes of text-related apis.

  • Plain text

  • Editable text

  • The text box


Plain Text

“Fabric.js text – Document”

🎁 Online preview of this section case – plain text

🎁 This section code repository

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const text = new fabric.Text('Thunder Monkey')
  canvas.add(text)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Create Text using new fabric.text, passing in the Text content as the first argument.

New Fabric.text also supports a second parameter that allows you to set Text styles, which will be covered in the next chapter as you scroll down the page.


Editable text IText

“Fabric.js editable text-document”

🎁 Online preview of this section case – editable text

🎁 This section code repository

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const itext = new fabric.IText('Thunder Monkey')
  canvas.add(itext)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

You can create editable Text using new fabric.itext in the same way as new Fabric.text.

IText has an extra capital “I” on the first letter of Text.


The text box Textbox

“Fabric.js text box – Document”

🎁 Online preview of this section case – text box

🎁 This section code repository

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const textbox = new fabric.Textbox('Lorum ipsum dolor sit amet', {
    width: 250
  })
  canvas.add(textbox)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Use New Fabric. Textbox to create text boxes.

Textbox The second argument to new fabric.Textbox is the object. Using width sets the width of the Textbox.

The contents of new Fabric.textbox are also editable.








Basic style

Common graphics Styles

In fact, there are a lot of style attributes, here only the commonly used attributes, other attributes can be consulted by the official documentation.

This example uses the circle as an example (don’t worry about the color scheme, I will enter the color randomly to demonstrate)

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const circle = new fabric.Circle({
    top: 100.left: 100.radius: 50.// Radius: 50px
    backgroundColor: 'green'.// Background color: green
    fill: 'orange'.// Fill color: orange
    stroke: '#f6416c'.// Frame color: pink
    strokeWidth: 5.// Border size: 5px
    strokeDashArray: [20.5.14].// Border dotted line rule: Fill 20px empty 5px fill 14px empty 20px fill 5px......
    shadow: '10px 20px 6px Rgba (10, 20, 30, 0.4)'.// Drop shadow: right 10px, down 20px, feather 6px, drop shadow color and transparency
    transparentCorners: false.// The Angle is filled when selected. True hollow; False solid
    borderColor: '#16f1fc'.// When selected, the border color is sky blue
    borderScaleFactor: 5.// When selected, the edge thickness is 5px
    borderDashArray: [20.5.10.7].// Rule for dotted lines when checked
    cornerColor: "#a1de93".// When selected, the corner color is cyan
    cornerStrokeColor: 'pink'.// When checked, the color of the corner border is pink
    cornerStyle: 'circle'.// When selected, the property called. Default rect rectangle; Circle the round
    cornerSize: 20.// When selected, the Angle size is 20
    cornerDashArray: [10.2.6].// When checked, the dotted line Angle rule
    selectionBackgroundColor: '#7f1300'.// When selected, the background color of the selection box is vermilion
    padding: 40.// When selected, the selection box should be 40px from the inner margin of the element
    borderOpacityWhenMoving: 0.6.// The object controls the opacity of the boundary as it moves and moves
  })

  canvas.add(circle)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

The above example has a normal state and a selected state. See the code comment for details.


Common text styles

🎁 This section case online preview – text style

🎁 This section code repository

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const text = new fabric.Text('ray monkeys', {
    top: 40.left: 40.fontSize: 120.backgroundColor: 'green'.// Background color: green
    fill: 'orange'.// Fill color: orange
    stroke: '#f6416c'.// Frame color: pink
    strokeWidth: 3.// Border size: 3px
    strokeDashArray: [20.5.14].// Border dotted line rule: Fill 20px empty 5px fill 14px empty 20px fill 5px......
    shadow: '10px 20px 6px Rgba (10, 20, 30, 0.4)'.// Drop shadow: right 10px, down 20px, feather 6px, drop shadow color and transparency
    transparentCorners: false.// The Angle is filled when selected. True hollow; False solid
    borderColor: '#16f1fc'.// When selected, the border color is sky blue
    borderScaleFactor: 5.// When selected, the edge thickness is 5px
    borderDashArray: [20.5.10.7].// Rule for dotted lines when checked
    cornerColor: "#a1de93".// When selected, the corner color is cyan
    cornerStrokeColor: 'pink'.// When checked, the color of the corner border is pink
    cornerStyle: 'circle'.// When selected, the property called. Default rect rectangle; Circle the round
    cornerSize: 20.// When selected, the Angle size is 20
    cornerDashArray: [10.2.6].// When checked, the dotted line Angle rule
    selectionBackgroundColor: '#7f1300'.// When selected, the background color of the selection box is vermilion
    padding: 40.// When selected, the selection box should be 40px from the inner margin of the element
    borderOpacityWhenMoving: 0.6.// The object controls the opacity of the boundary as it moves and moves
  })

  canvas.add(text)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

In addition, you can configure underscores, underscores, strikeout, left alignment, right alignment, center alignment, and line spacing.

<template>
  <canvas width="600" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / on line
  const overline = new fabric.Text('overline', {
    top: 30.left: 10.fontSize: 20.overline: true./ / on line
  })

  / / the underline
  const underline = new fabric.Text('underline', {
    top: 30.left: 100.fontSize: 20.underline: true./ / the underline
  })

  / / delete line
  const linethrough = new fabric.Text('Delete line', {
    top: 30.left: 200.fontSize: 20.linethrough: true./ / delete line
  })

  / / left alignment
  const msg1 = 'Left \n left \n left aligned'
  const left = new fabric.Text(msg1, {
    top: 100.left: 10.fontSize: 16.textAlign: 'left'./ / left alignment
  })

  // Center and align
  const msg2 = 'Center \n center \n center aligned'
  const center = new fabric.Text(msg2, {
    top: 100.left: 100.fontSize: 16.textAlign: 'center'.// Center and align
  })

  / / right alignment
  const msg3 = 'Right \n right \n right aligned'
  const right = new fabric.Text(msg3, {
    top: 100.left: 200.fontSize: 16.textAlign: 'right'./ / right alignment
  })

  // Text content
  const msg4 = "Lorem ipsum dolor sit amet,\nconsectetur adipisicing elit,\nsed do eiusmod tempor incididunt\nut labo"
  
  const lineHeight1 = new fabric.Text(msg4, {
    top: 250.left: 10.fontSize: 16.lineHeight: 1./ / line height
  })

  const lineHeight2 = new fabric.Text(msg4, {
    top: 250.left: 300.fontSize: 16.lineHeight: 2./ / line height
  })

  canvas.add(
    overline,
    underline,
    linethrough,
    left,
    center,
    right,
    lineHeight1,
    lineHeight2
  )

}

onMounted(() = > {
  init()
})
</script>
Copy the code

The configuration of the hyphen, underscore, and delete line can be used simultaneously.








The gradient

“Fabric.js Gradient – Document”

🎁 Online preview of this section case – Gradient

🎁 This section code repository

Linear gradient

<template>
  <canvas width="600" height="600" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  let canvas = new fabric.Canvas('canvas') // Instantiate fabric and bind it to the Canvas element

  / / round
  let circle = new fabric.Circle({
    left: 100.top: 100.radius: 50,})// Linear gradient
  let gradient = new fabric.Gradient({
    type: 'linear'.// linear or radial
    gradientUnits: 'pixels'.// Pixels or pencentage Pixels or percentage
    coords: { x1: 0.y1: 0.x2: circle.width, y2: 0 }, // At least two coordinate pairs (x1, y1, and x2, y2) will define how the gradient expands on the object
    colorStops: [// Define an array of gradient colors
      { offset: 0.color: 'red' },
      { offset: 0.2.color: 'orange' },
      { offset: 0.4.color: 'yellow' },
      { offset: 0.6.color: 'green' },
      { offset: 0.8.color: 'blue' },
      { offset: 1.color: 'purple' },
    ]
  })
  circle.set('fill', gradient);
  canvas.add(circle)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Radial gradient

<template>
  <canvas width="600" height="600" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  let canvas = new fabric.Canvas('canvas')  // Instantiate fabric and bind it to the Canvas element

  / / round
  let circle = new fabric.Circle({
    left: 100.top: 100.radius: 50,})let gradient = new fabric.Gradient({
    type: 'radial'.coords: {
      r1: 50.// This property is only available for radial gradient, outer circle radius
      r2: 0.// This property is only available for radial gradient, outer circle radius
      x1: 50.// The x coordinate of the focus
      y1: 50.// The y-coordinate of the focus
      x2: 50.// The x-coordinate of the center point
      y2: 50.// The y-coordinate of the center point
    },
    colorStops: [{offset: 0.color: '#fee140' },
      { offset: 1.color: '#fa709a' }
    ]
  })

  circle.set('fill', gradient);
  canvas.add(circle)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

R1, R2, X1, Y1, X2, y2 these parameters can be modified by yourself and then see the effect. You can understand more deeply by yourself.








Use pictures

“Fabric.js images – Documentation”

🎁 Online preview of this section case – using images

🎁 This section code repository

Method 1: Use HTML images

<template>
  <div>
    <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
    <img src="@/assets/logo.png" id="logo">
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const imgElement = document.getElementById('logo')

  imgElement.onload = function() {
    let imgInstance = new fabric.Image(imgElement, {
      left: 100.top: 100.width: 200.height: 200.angle: 50./ / rotation
    })
    canvas.add(imgInstance)
  }

}

onMounted(() = > {
  init()
})
</script>

<style>
#logo {
  display: none;
}
</style>

Copy the code

You need to use the onload method to listen to see if the image is loaded.

The image will not be displayed until it is fully loaded and then added to the canvas.


Using this method, if you don’t want to display the image outside the canvas, use display: None; Hide the pictures.


Method 2: Use JS import

<template>
  <div>
    <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'
import logo from '@/assets/logo.png' // Import images

function init() {
  const canvas = new fabric.Canvas('canvas')

  fabric.Image.fromURL(logo, oImg= > {
    oImg.scale(0.5) / / zoom
    canvas.add(oImg) // Add the image to the canvas
  })
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Use fabric.image.fromurl to load images.

The first parameter is the image resource, which can put local images or network images.

The second argument is a callback function that operates on the image object once the image is loaded.








Image filter

“Fabric.js Image Path – Document”

🎁 Online preview of this section case – Image filter

🎁 This section code repository

<template>
  <div>
    <canvas width="500" height="500" id="canvas" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'
import gwen from '@/assets/images/gwen-spider-verse-ah.jpg'

function init() {
  const canvas = new fabric.Canvas('canvas')

  fabric.Image.fromURL(gwen, img= > {
    img.scale(0.5) // Shrink the image by 50%
    canvas.add(img)
  })

  // Single filter
  fabric.Image.fromURL(gwen, img= > {
    img.scale(0.5) // Shrink the image by 50%
    img.left = 250
    // Add a filter
    img.filters.push(new fabric.Image.filters.Grayscale())
    // After the image is loaded, apply the filter effect
    img.applyFilters()
    canvas.add(img)
  })

  // Add a filter
  // The "filters" property is an array. We can use the array method to do whatever we want: remove filters (pop, splice, shift), add filters (push, unshift, splice), and even combine multiple filters. When we call applyFilters, any filters that are in the "Filters" array will be applied one by one, so let's try to create an image that is both polarized and bright.
  fabric.Image.fromURL(gwen, img= > {
    img.scale(0.5) // Shrink the image by 50%
    // Add a filter
    img.filters.push(
        new fabric.Image.filters.Grayscale(),
        new fabric.Image.filters.Sepia(), / / color
        new fabric.Image.filters.Brightness({ brightness: 0.2 }) / / brightness
    )
    // After the image is loaded, apply the filter effect
    img.applyFilters()
    img.set({
      left: 250.top: 250,
    })

    canvas.add(img)
  })
}

onMounted(() = > {
  init()
})
</script>
Copy the code

To add a filter to an Image, the fabric.image. fromURL callback returns an Image object that can be filtered using filters.


Fabric has built-in filters

  • BaseFilter Basic filter

  • The Blur Blur

  • Brightness Brightness

  • ColorMatrix ColorMatrix

  • Contrast Contrast

  • Convolute convolution

  • Gamma Gamma

  • Grayscale gray

  • HueRotation tone rotation

  • Invert the horse

  • Noise Noise

  • Pixelate pixelated

  • RemoveColor removes the color

  • Resize Resize

  • Saturation saturated

  • Sepia color








conversion

Rotation Angle

<template>
  <div>
    <canvas width="500" height="500" id="canvas" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  let triangle = new fabric.Triangle({
    top: 100.left: 100.width: 80.height: 100.fill: 'blue'.angle: 30 // Rotate 30 degrees
  })

  canvas.add(triangle)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Scale scaleX and scaleY

<template>
  <div>
    <canvas width="500" height="500" id="canvas" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  let triangle = new fabric.Triangle({
    top: 100.left: 100.width: 80.height: 100.fill: 'blue'.scaleX: 2.// Zoom in 2x
    scaleY: 2 // Zoom in the y direction 2 times
  })

  canvas.add(triangle)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Reverse scaleX and scaleY

<template>
  <div>
    <canvas width="500" height="500" id="canvas" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  let triangle = new fabric.Triangle({
    top: 100.left: 100.width: 80.height: 100.fill: 'blue'.scaleY: -1 // When scale is negative, the graph reverses
  })

  canvas.add(triangle)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Shift top and left

The top and left elements can be panned directly.

Refer to the previous example.








grouping

“Fabric.js group – Documents”

Build group

🎁 Online preview of this section – Group creation and operation

🎁 This section code repository

<template>
  <div>
    <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / oval
  const ellipse = new fabric.Ellipse({
    top: 20.left: 20.rx: 100.ry: 50.fill: '#ddd'.originX: 'center'.// Rotate the X-axis: left, right, center
    originY: 'center' // Rotate the Y-axis: top, bottom, center
  })

  / / text
  const text = new fabric.Text('Hello World', {
    top: 40.left: 20.fontSize: 20.originX: "center".originY: "center"
  })

  / / building group
  const group = new fabric.Group([ellipse, text], {
    top: 50.// The whole group is 100 away from the top
    left: 100.// The whole group is 100 to the left
    angle: -10.// The whole group is rotated -10deg
  })

  canvas.add(group)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

New fabric.Group creates a Group (similar to groups in Photoshop, where multiple layers are placed in the same Group to perform synchronized operations such as drag and zoom).


The operations group

🎁 Online preview of this section – Group creation and operation

🎁 This section code repository


The fabric.js group provides a number of methods. Here are some common ones:

  • getObjects()Returns an array of all objects in a set
  • size()The number of all objects
  • contains()Checks whether a particular object is presentgroup
  • item()Element in the set of
  • forEachObject()Iterate over the objects in the group
  • add()Add element object
  • remove()Deleting element objects
  • fabric.util.object.clone()cloning


Let me take one example: item()

Based on the previous example, change the ellipse to red and change “Hello World” to “Thunder Monkey, World”.


<template>
  <div>
    <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / oval
  const ellipse = new fabric.Ellipse({
    top: 20.left: 20.rx: 100.ry: 50.fill: '#ddd'.originX: 'center'.// Rotate the X-axis: left, right, center
    originY: 'center' // Rotate the Y-axis: top, bottom, center
  })

  / / text
  const text = new fabric.Text('Hello World', {
    top: 40.left: 20.fontSize: 20.originX: "center".originY: "center"
  })

  / / building group
  const group = new fabric.Group([ellipse, text], {
    top: 50.// The whole group is 100 away from the top
    left: 100.// The whole group is 100 to the left
    angle: -10.// The whole group is rotated -10deg
  })

  // Control the first element (ellipse)
  group.item(0).set('fill'.'#ea5455')

  // Control the second element (text)
  group.item(1).set({
    text: Thunder Monkey, The World.fill: '#fff'
  })

  canvas.add(group)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Scattered grouping

🎁 Online preview of the case in this section – Group building and Group breaking

🎁 This section code repository

<template>
  <div>
    <button @click="ungroup">Cancel the group</button>
    <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

let canvas = null

/ / initialization
function init() {
  canvas = new fabric.Canvas('canvas')

  / / oval
  const ellipse = new fabric.Ellipse({
    top: 20.left: 20.rx: 100.ry: 50.fill: '#ddd'.originX: 'center'.// Rotate the X-axis: left, right, center
    originY: 'center' // Rotate the Y-axis: top, bottom, center
  })

  / / text
  const text = new fabric.Text('Hello World', {
    top: 40.left: 20.fontSize: 20.originX: "center".originY: "center"
  })

  / / building group
  const group = new fabric.Group([ellipse, text], {
    top: 50.// The whole group is 100 away from the top
    left: 100.// The whole group is 100 to the left
    angle: -10.// The whole group is rotated -10deg
  })

  canvas.add(group)
}

/ / cancel the group
function ungroup() {
  // Check whether the element is currently selected, if not, do nothing
  if(! canvas.getActiveObject()) {return
  }

  // Determine whether the group is currently selected. If not, no action is performed
  if(canvas.getActiveObject().type ! = ='group') {
    return
  }

  // Get the currently selected object, and then shatter it
  canvas.getActiveObject().toActiveSelection()
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Use Canvas.getActiveObject () to get the currently selected object of the canvas, and then use toActiveSelection() to split the group.








animation

“Fabric.js animate – Document”

🎁 This section case online preview – animation

🎁 This section code repository


Absolute value animation

Forget about absolute value animation and relative value animation for a moment, and you’ll see after this.

This section is the basic use of animation.

<template>
  <div>
    <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

/ / initialization
function init() {
  const canvas = new fabric.Canvas('canvas')

  const rect = new fabric.Rect({
    left: 100.top: 100.width: 100.height: 100.fill: 'red'
  })

  // Set the rectangle animation
  rect.animate('angle'."To 50", {
    onChange:canvas.renderAll.bind(canvas), // It is executed every time it is refreshed
  })

  canvas.add(rect)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Each Fabric object has an animate method, which animates the object.


Use: animate(animate property, end value of animation, details of drawing)


The first parameter is to set the properties of the animation.

The second parameter is the end value of the animation.

The third argument is an object that contains:

{ROM: allows you to specify the starting value of an animatable property (if we do not want to use the current value). Duration: Default 500 (ms). Can be used to change the duration of an animation. OnComplete: Callback called at the end of the animation. Easing: Easing function. }Copy the code


Relative value animation

<template>
  <div>
    <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

/ / initialization
function init() {
  const canvas = new fabric.Canvas('canvas')
  const rect = new fabric.Rect({
    left: 100.top: 100.width: 100.height: 100.fill: 'red'
  })

  // Notice the second argument: +=360
  rect.animate('angle'.'+ = 360', {
    onChange:canvas.renderAll.bind(canvas), // It is executed every time it is refreshed
    duration: 2000.// Execution time
    easing: fabric.util.ease.easeOutBounce, // Buffer effect
  })

  canvas.add(rect)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

This example with the fabric. Util. Ease. EaseOutBounce buffer effect.


In fact, the use of absolute value animation and relative value animation is almost the same, but the use of the second parameter is different.

Relative value animation changes animate to a value with an operator, which will perform calculations on the original basis.








The event

🎁 This section case online preview – Events

🎁 This section code repository


Fabric.js provides a convenient event system that can initialize event listeners using the ON method and remove them using the off method.

<template>
  <div>
    <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
    <button @click="addClickEvent">Add canvas click event</button>
    <button @click="removeClickEvent">Removes the canvas click event</button>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

let canvas = null

// Initialize the canvas
function init() {
  canvas = new fabric.Canvas('canvas')

  const rect = new fabric.Rect({
    top: 20.left: 20.width: 100.height: 50.fill: '#9896f1'
  })

  // Add a select event to the rectangle
  rect.on('selected'.options= > {
    console.log('Rectangle selected', options)
  })
  canvas.add(rect)

  addClickEvent()
}

// Remove the canvas click event
function removeClickEvent() {
  canvas.off('mouse:down')}// Add canvas click events
function addClickEvent() {
  removeClickEvent() // Clear the event before adding it to avoid adding it again
  canvas.on('mouse:down'.options= > {
    console.log(X-axis coordinates:${options.e.clientX}; Y-axis coordinates:${options.e.clientY}`)
  })
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Fabric.js also provides a number of events; see the official case for details








Free drawing

“Fabric.js Free drawing – Documentation”

🎁 Online preview of this section case – Free drawing

🎁 This section code repository

<template>
  <div>
    <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

/ / initialization
function init() {
  const canvas = new fabric.Canvas('canvas', {
    isDrawingMode: true.// Enable drawing mode
  })

  // Set the brush color
  canvas.freeDrawingBrush.color = '#11999e'

  // Set the brush thickness
  canvas.freeDrawingBrush.width = 10

  // Brush projection
  canvas.freeDrawingBrush.shadow = new fabric.Shadow({
    blur: 10.offsetX: 10.offsetY: 10.affectStroke: true.color: '#30e3ca',
  })
}

onMounted(() = > {
  init()
})
</script>
Copy the code

When creating a Canvas using new Fabric. Canvas, set isDrawingMode: true to begin free painting mode.

Canvas. FreeDrawingBrush has a bunch of properties to set brush styles.








Disable partial operations

🎁 Online preview of cases in this section – Disable some operations

🎁 This section code repository

Forbid horizontal movement

<template>
  <div>
    <canvas id="canvas" width="400" height="400" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

// Initialize the canvas
function init() {
  const canvas = new fabric.Canvas('canvas')

  const rect = new fabric.Rect({
    top: 100.left: 100.width: 100.height: 50.fill: '#ffde7d'
  })

  // Horizontal movement is not allowed
  rect.lockMovementX = true

  canvas.add(rect)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Use lockMovementX to disallow horizontal movement of objects.


No vertical movement

<template>
  <div>
    <canvas id="canvas" width="400" height="400" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

// Initialize the canvas
function init() {
  const canvas = new fabric.Canvas('canvas')

  const rect = new fabric.Rect({
    top: 100.left: 100.width: 100.height: 50.fill: '#f6416c'
  })

  // Vertical movement is not allowed
  rect.lockMovementY = true

  canvas.add(rect)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Use lockMovementY to disable vertical movement of objects.


Ban rotation

<template>
  <div>
    <canvas id="canvas" width="400" height="400" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

// Initialize the canvas
function init() {
  const canvas = new fabric.Canvas('canvas')

  const rect = new fabric.Rect({
    top: 100.left: 100.width: 100.height: 50.fill: '#3490de'
  })

  // Disable rotation
  rect.lockRotation = true

  canvas.add(rect)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Use the lockRotation to disable object rotation.


Forbid horizontal scaling

<template>
  <div>
    <canvas id="canvas" width="400" height="400" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

// Initialize the canvas
function init() {
  const canvas = new fabric.Canvas('canvas')

  const rect = new fabric.Rect({
    top: 100.left: 100.width: 100.height: 50.fill: '#ff9a3c'
  })

  // Disable horizontal scaling
  rect.lockScalingX = true

  canvas.add(rect)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Use lockScalingX to disable horizontal scaling of objects.


Forbid vertical scaling

<template>
  <div>
    <canvas id="canvas" width="400" height="400" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

// Initialize the canvas
function init() {
  const canvas = new fabric.Canvas('canvas')

  const rect = new fabric.Rect({
    top: 100.left: 100.width: 100.height: 50.fill: '#f95959'
  })

  // Forbid vertical scaling
  rect.lockScalingY = true

  canvas.add(rect)
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Use lockScalingY to disable vertical scaling of objects.








Scale and pan the canvas

🎁 Online preview of this section case – Pan and scale the canvas

🎁 This section code repository

Zoom the canvas

Scale the canvas based on the origin

To scale the canvas, you’re actually listening for mouse events.

This listens for the mouse wheel event: mouse:wheel.

<template>
  <div>
    <canvas id="canvas" width="400" height="400" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  // Initialize the canvas
  const canvas = new fabric.Canvas('canvas')

  // rectangle (reference)
  const rect = new fabric.Rect({
    top: 10.left: 10.width: 40.height: 40.fill: 'orange'
  })

  // circle
  const circle = new fabric.Circle({
    top: 30.left: 30.radius: 50.fill: 'green'
  })
  canvas.add(rect, circle) // Add the rectangle and circle to the canvas

  // Listen for mouse wheel events
  canvas.on('mouse:wheel'.opt= > {
    let delta = opt.e.deltaY // Roll the wheel up to -100, roll it down to 100
    let zoom = canvas.getZoom() // Gets the canvas's current scale value

    // Control the zoom range from 0.01 to 20
    zoom *= 0.999 ** delta
    if (zoom > 20) zoom = 20
    if (zoom < 0.01) zoom = 0.01

    // Set the canvas scale
    canvas.setZoom(zoom)
  })
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Scale the canvas against the mouse pointer

<template>
  <div>
    <canvas id="canvas" width="400" height="400" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  // Initialize the canvas
  const canvas = new fabric.Canvas('canvas')

  // rectangle (reference)
  const rect = new fabric.Rect({
    top: 130.left: 130.width: 40.height: 40.fill: 'orange'
  })

  // circle
  const circle = new fabric.Circle({
    top: 150.left: 150.radius: 50.fill: 'green'
  })
  canvas.add(rect, circle) // Add the rectangle and circle to the canvas

  // Listen for mouse wheel events
  canvas.on('mouse:wheel'.opt= > {
    let delta = opt.e.deltaY // Roll the wheel up to -100, roll it down to 100
    let zoom = canvas.getZoom() // Gets the canvas's current scale value

    // Control the zoom range from 0.01 to 20
    zoom *= 0.999 ** delta
    if (zoom > 20) zoom = 20
    if (zoom < 0.01) zoom = 0.01

    // Set the canvas scale
    // Key point!!
    // Parameter 1: Sets the point of the canvas to the current mouse position
    // Argument 2: pass in the scale value
    canvas.zoomToPoint(
      {
        x: opt.e.offsetX, // Mouse x coordinates
        y: opt.e.offsetY  // Mouse Y-axis coordinates
      },
      zoom // The last value to scale
    )
  })
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Translation canvas

The requirement for this example is that the move canvas function is triggered only after the Alt key is pressed.

Based on this requirement, the task can be broken down into 3 steps:

  • Mouse click (the moment it is pressed)
  • The mouse moves
  • Release the mouse


Click mouse: Down

  1. This step can be listened on using mouse:down.

  2. Listen for Alt to be pressed in the callback function.

  3. If Alt is pressed, set a value record to enable movement.

  4. Record the x and y coordinates of the mouse.


Mouse move :move

  1. Determine if you need to move (the third mouse click).
  2. If you need to move, switch canvas view mode immediately
  3. Move the canvas toMouse x and y coordinates


Release the mouse: Up

  1. Freeze the canvas at the coordinates where the mouse is released.
  2. Off moving state(Mouse click on the third step)

<template>
  <div>
    <canvas id="canvas" width="400" height="400" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  // Initialize the canvas
  const canvas = new fabric.Canvas('canvas')

  // rectangle (reference)
  const rect = new fabric.Rect({
    top: 130.left: 130.width: 40.height: 40.fill: 'orange'
  })

  // circle
  const circle = new fabric.Circle({
    top: 150.left: 150.radius: 50.fill: 'green'
  })
  canvas.add(rect, circle) // Add the rectangle and circle to the canvas

  canvas.on('mouse:down'.opt= > { // Triggered when the mouse is pressed
    let evt = opt.e
    if (evt.altKey === true) { // Whether to hold Alt
      canvas.isDragging = true // isDragging is custom, enable movement state
      canvas.lastPosX = evt.clientX // lastPosX is custom
      canvas.lastPosY = evt.clientY // lastPosY is custom
    }
  })

  canvas.on('mouse:move'.opt= > { // Triggered when the mouse moves
    if (canvas.isDragging) {
      let evt = opt.e
      let vpt = canvas.viewportTransform // Focus view conversion
      vpt[4] += evt.clientX - canvas.lastPosX
      vpt[5] += evt.clientY - canvas.lastPosY
      canvas.requestRenderAll() // re-render
      canvas.lastPosX  = evt.clientX
      canvas.lastPosY  = evt.clientY
    }
  })

  canvas.on('mouse:up'.opt= > { // Triggered when the mouse is released
    canvas.setViewportTransform(canvas.viewportTransform) // Sets the viewport conversion for this canvas instance
    canvas.isDragging = false // Turn off the move state
  })
}

onMounted(() = > {
  init()
})
</script>
Copy the code








selected

“Original address”

🎁 This section case online preview – Selected status

🎁 This section code repository

Fabric.js creates elements (graphics, pictures, groups, etc.) that can be selected by default.

Whether it can be selected.

Can I select blank space?

The selected style.


Ban on selected

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const rect = new fabric.Rect({
    top: 100.left: 100.width: 200.height: 100.fill: 'red'
  })

  // The element is disabled
  rect.selectable = false

  canvas.add(rect)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Elements cannot be selected through blank space


The blue triangle can only be selected when the mouse is fully in place

<template>
  <canvas width="400" height="400" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / triangle
  const triangle1 = new fabric.Triangle({
    top: 100.left: 50.width: 80.// The bottom width
    height: 100.// The distance between the base and the fixed point
    fill: 'blue',})If perPixelTargetFind is set to false, it can be selected. The default value is false
  triangle1.perPixelTargetFind = true

  / / triangle
  const triangle2 = new fabric.Triangle({
    top: 100.left: 200.width: 80.// The bottom width
    height: 100.// The distance between the base and the fixed point
    fill: 'green',
  })


  canvas.add(triangle1, triangle2)
  canvas.selectionFullyContained = true // Select only the shapes that are fully contained in the drag selection rectangle
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Canvas box selection style

<template>
  <canvas width="200" height="200" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / round
  const circle = new fabric.Circle({
    radius: 30.fill: '#f55'.top: 70.left: 70
  })

  canvas.add(circle)

  canvas.selection = true // Whether the canvas is selectable. The default true; False Unselected
  canvas.selectionColor = 'rgba (106, 101, 216, 0.3)' // Canvas the background color of the mouse box selection
  canvas.selectionBorderColor = "#1d2786" // The color of the canvas mouse frame
  canvas.selectionLineWidth = 6 // The thickness of the canvas's frame
  canvas.selectionDashArray = [30.4.10] // Canvas mouse frame selection border dotted line rule
  canvas.selectionFullyContained = true // Select only the shapes that are fully contained in the drag selection rectangle
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Custom edge and control Angle styles

<template>
  <canvas width="200" height="200" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / round
  const circle = new fabric.Circle({
    radius: 30.fill: '#f55'.top: 70.left: 70
  })

  circle.set({
    borderColor: 'red'.// Border color
    cornerColor: 'green'.// Control the Angle color
    cornerSize: 10.// Control Angle size
    transparentCorners: false // Control Angle fill color is opaque
  })

  canvas.add(circle)

  canvas.setActiveObject(circle) / / select the circle
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Transparent control Angle

<template>
  <canvas width="200" height="200" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / round
  const circle = new fabric.Circle({
    radius: 30.fill: '#f55'.top: 70.left: 70
  })

  circle.set({
    borderColor: 'gray'.// Border color
    cornerColor: 'black'.// Control the Angle color
    cornerSize: 12.// Control Angle size
    transparentCorners: true // Control Angle fill color transparent
  })

  canvas.add(circle)

  canvas.setActiveObject(circle) // select the first item
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Customize the selected background color

<template>
  <canvas width="200" height="200" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / round
  const circle = new fabric.Circle({
    radius: 30.fill: '#f55'.top: 70.left: 70
  })

  circle.set({
    selectionBackgroundColor: 'orange' // The background color changes to orange
  })

  canvas.add(circle)

  canvas.setActiveObject(circle) // select the first item
}

onMounted(() = > {
  init()
})
</script>
Copy the code


No border

<template>
  <canvas width="200" height="200" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / round
  const circle = new fabric.Circle({
    radius: 30.fill: '#f55'.top: 70.left: 70
  })

  circle.hasBorders = false // Remove the border

  canvas.add(circle)

  canvas.setActiveObject(circle) // select the first item
}

onMounted(() = > {
  init()
})
</script>
Copy the code


No control Angle

No control Angle will mean that scaling and rotation cannot be manipulated directly with the mouse, allowing only movement operations.

<template>
  <canvas width="200" height="200" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / round
  const circle = new fabric.Circle({
    radius: 30.fill: '#f55'.top: 70.left: 70
  })

  circle.hasControls = false // Disable the control Angle

  canvas.add(circle)

  canvas.setActiveObject(circle) // select the first item
}

onMounted(() = > {
  init()
})
</script>
Copy the code


The custom cursor hovers over an object

This example sets the “wait pointer” when the mouse appears over an element.

<template>
  <canvas width="200" height="200" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / round
  const circle = new fabric.Circle({
    radius: 30.fill: '#f55'.top: 70.left: 70
  })

  canvas.hoverCursor = 'wait' // Set the wait pointer

  canvas.add(circle)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


The style of the element as it moves

<template>
  <canvas width="200" height="200" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / round
  const circle = new fabric.Circle({
    radius: 30.fill: '#f55'.top: 70.left: 70
  })

  circle.hasBorders = circle.hasControls = false

  canvas.add(circle)

  function animate(e, dir) {
    if (e.target) {
      fabric.util.animate({
        startValue: e.target.get('angle'),
        endValue: e.target.get('angle') + (dir ? 10 : -10),
        duration: 100
      })
      fabric.util.animate({
        startValue: e.target.get('scaleX'),
        endValue: e.target.get('scaleX') + (dir ? 0.2 : -0.2),
        duration: 100.onChange: function(value) {
          e.target.scale(value)
          canvas.renderAll()
        },
        onComplete: function() {
          e.target.setCoords()
        }
      })
    }
  }
  canvas.on('mouse:down'.function(e) { animate(e, 1) })
  canvas.on('mouse:up'.function(e) { animate(e, 0) })
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Box selection is not allowed

Does not allow selection from the canvas box, but allows selection of elements.

<template>
  <canvas width="200" height="200" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  / / round
  const circle = new fabric.Circle({
    radius: 30.fill: '#f55'.top: 70.left: 70
  })

  canvas.add(circle)
  canvas.selection = false // Do not select directly from the canvas box
}

onMounted(() = > {
  init()
})
</script>
Copy the code








tailoring

“Fabric.js clipping text 1”

“Fabric.js clipping text 2”

🎁 This section case online preview – clipping

🎁 This section code repository

Clipping single figure

<template>
  <canvas width="300" height="300" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  // Clipped graphics
  // clipPath starts from the center of the object, objects originX and originY have no effect, while clipPath originX and originY have effect. The positioning logic is the same as fabric.group
  const clipPath = new fabric.Circle({
    radius: 40.left: -40.top: -40
  })

  / / rectangle
  const rect = new fabric.Rect({
    width: 200.height: 100.fill: 'red'
  })

  // Cut the rectangle
  rect.clipPath = clipPath

  canvas.add(rect)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Clipping a group

<template>
  <canvas width="300" height="300" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  // Clipped graphics
  // clipPath starts from the center of the object, objects originX and originY have no effect, while clipPath originX and originY have effect. The positioning logic is the same as fabric.group
  const clipPath = new fabric.Circle({
    radius: 40.left: -40.top: -40
  })

  const group = new fabric.Group([
    new fabric.Rect({ width: 100.height: 100.fill: 'red' }),
    new fabric.Rect({ width: 100.height: 100.fill: 'yellow'.left: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: 'blue'.top: 100 }),
    new fabric.Rect({
      width: 100.height: 100.fill: 'green'.left: 100.top: 100})])// Clipping a group
  group.clipPath = clipPath

  canvas.add(group)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Combination of clips

<template>
  <canvas width="300" height="300" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const clipPath = new fabric.Group(
    [
      new fabric.Circle({ radius: 70.top: -70.left: -70 }),
      new fabric.Circle({ radius: 40.top: -95.left: -95 }),
      new fabric.Circle({ radius: 40.top: 15.left: 15{})],left: -95.top: -95})const group = new fabric.Group([
    new fabric.Rect({ width: 100.height: 100.fill: 'red' }),
    new fabric.Rect({ width: 100.height: 100.fill: 'yellow'.left: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: 'blue'.top: 100 }),
    new fabric.Rect({
      width: 100.height: 100.fill: 'green'.left: 100.top: 100
    })
  ])

  group.clipPath = clipPath
  canvas.add(group)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Cut after cut (combination clip)

<template>
  <canvas width="300" height="300" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const clipPath = new fabric.Circle({ radius: 70.top: -50.left: -50 })
  const innerClipPath = new fabric.Circle({ radius: 70.top: -90.left: -90 })
  clipPath.clipPath = innerClipPath

  const group = new fabric.Group([
    new fabric.Rect({ width: 100.height: 100.fill: 'red' }),
    new fabric.Rect({ width: 100.height: 100.fill: 'yellow'.left: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: 'blue'.top: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: 'green'.left: 100.top: 100 }),
  ])

  group.clipPath = clipPath
  canvas.add(group)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Group nested clips

<template>
  <canvas width="300" height="300" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const clipPath = new fabric.Circle({ radius: 100.top: -100.left: -100 })
  const small = new fabric.Circle({ radius: 50.top: -50.left: -50 })

  const group = new fabric.Group([
    new fabric.Rect({ width: 100.height: 100.fill: "red".clipPath: small }),
    new fabric.Rect({ width: 100.height: 100.fill: "yellow".left: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: "blue".top: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: "green".left: 100.top: 100 }),
  ])

  group.clipPath = clipPath
  canvas.add(group)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Crop it with text

<template>
  <canvas width="300" height="300" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas')

  const clipPath = new fabric.Text(
    'Hi I\'m the \nnew ClipPath! \nI hope we\'ll\nbe friends',
    { top: -100.left: -100})const group = new fabric.Group([
    new fabric.Rect({ width: 100.height: 100.fill: "red" }),
    new fabric.Rect({ width: 100.height: 100.fill: "yellow".left: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: "blue".top: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: "green".left: 100.top: 100 }),
  ])

  group.clipPath = clipPath
  canvas.add(group)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Cut out the canvas

<template>
  <canvas width="300" height="300" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas', {
    backgroundColor: "#ddd"
  })

  const group = new fabric.Group([
    new fabric.Rect({ width: 100.height: 100.fill: "red" }),
    new fabric.Rect({ width: 100.height: 100.fill: "yellow".left: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: "blue".top: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: "green".left: 100.top: 100}),])const clipPath = new fabric.Circle({ radius: 100.top: 0.left: 50 })
  canvas.clipPath = clipPath
  canvas.add(group)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Crop the canvas, but not the controls

<template>
  <canvas width="300" height="300" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas', {
    backgroundColor: "#ddd"
  })

  const group = new fabric.Group([
    new fabric.Rect({ width: 100.height: 100.fill: "red" }),
    new fabric.Rect({ width: 100.height: 100.fill: "yellow".left: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: "blue".top: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: "green".left: 100.top: 100}),])// Controls are visible outside the clipping area
  canvas.controlsAboveOverlay = true

  const clipPath = new fabric.Circle({ radius: 100.top: 0.left: 50 })
  canvas.clipPath = clipPath
  canvas.add(group)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Animation cutting

<template>
  <canvas width="300" height="300" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas('canvas', {
    backgroundColor: "#ddd"
  })

  const clipPath = new fabric.Rect({ width: 100.height: 100.top: 0.left: 0 })

  function animateLeft(){
    clipPath.animate({
      left: 200}, {duration: 900.onChange: canvas.requestRenderAll.bind(canvas),
      onComplete: animateRight
    })
  }

  function animateRight(){
    clipPath.animate({
      left: 0}, {duration: 1200.onChange: canvas.requestRenderAll.bind(canvas),
      onComplete: animateLeft
    })
  }

  function animateDown(){
    clipPath.animate({
      top: 100}, {duration: 500.onChange: canvas.requestRenderAll.bind(canvas),
      onComplete: animateUp
    })
  }

  function animateUp(){
    clipPath.animate({
      top: 0}, {duration: 400.onChange: canvas.requestRenderAll.bind(canvas),
      onComplete: animateDown
    })
  }

  const group = new fabric.Group([
    new fabric.Rect({ width: 100.height: 100.fill: "red" }),
    new fabric.Rect({ width: 100.height: 100.fill: "yellow".left: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: "blue".top: 100 }),
    new fabric.Rect({ width: 100.height: 100.fill: "green".left: 100.top: 100}),] and {scale: 1.5
  })

  canvas.controlsAboveOverlay = true

  animateLeft()
  animateDown()

  canvas.clipPath = clipPath
  canvas.add(group)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Use absolute positioning clipping

<template>
  <canvas width="300" height="300" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas("canvas")

  const clipPath = new fabric.Rect({ width: 300.height: 300.top: 0.left: 0.absolutePositioned: true })

  const clipPath2 = new fabric.Rect({ width: 300.height: 300.top: 0.left: 0.absolutePositioned: true })

  fabric.Image.fromURL("http://fabricjs.com/assets/dragon.jpg".function(img){
    img.clipPath = clipPath
    img.scaleToWidth(300)
    canvas.add(img)
  })

  fabric.Image.fromURL("http://fabricjs.com/assets/dragon2.jpg".function(img){
    img.clipPath =clipPath2
    img.scaleToWidth(300)
    img.top = 150
    canvas.add(img)
  })
}

onMounted(() = > {
  init()
})
</script>
Copy the code


Reverse clipPaths

<template>
  <canvas width="300" height="300" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const canvas = new fabric.Canvas("canvas")

  const clipPath = new fabric.Circle({ radius: 100.top: -200.left: -220 })
  const clipPath2 = new fabric.Circle({ radius: 100.top: 0.left: -20 })
  const clipPath3 = new fabric.Circle({ radius: 100.top: 0.left: -220 })
  const clipPath4 = new fabric.Circle({ radius: 100.top: -200.left: -20 })
  const g = new fabric.Group([ clipPath, clipPath2, clipPath3, clipPath4 ])

  g.inverted = true // Reverse clipping

  fabric.Image.fromURL("http://fabricjs.com/assets/dragon.jpg".function(img) {
    img.clipPath = g
    img.scaleToWidth(500)
    canvas.add(img)
  })
}

onMounted(() = > {
  init()
})
</script>
Copy the code








serialization

🎁 Online preview of this section case – serialization

🎁 This section code repository

Serialization is simply converting the contents of the canvas into JSON for easy storage.

But in addition to turning a canvas into a string, fabric.js can also output Base64 and SVG.

Output JSON

<template>
  <div>
    <canvas id="canvas" width="200" height="200" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  // Initialize the canvas
  const canvas = new fabric.Canvas('canvas')

  console.log('canvas stringify '.JSON.stringify(canvas))
  console.log('canvas toJSON', canvas.toJSON())
  console.log('canvas toObject', canvas.toObject())
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Open the console to see the output.


This example serializes an empty canvas using json.stringify (), canvas.tojson (), and Canvas.toobject (), respectively.

Fabric.js provides toJSON and toObject methods to convert the canvas and content toJSON.


Because this output is an empty canvas, the Objects field in the output is an empty array.

If there are elements such as backgrounds and graphics, data will appear in the objects object.

For details, see 🎁 online preview of this section’s case – serialization


PNG output (Base64)

<template>
  <div>
    <canvas id="canvas" width="200" height="200" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  // Initialize the canvas
  const canvas = new fabric.Canvas('canvas', {
    backgroundColor: '#a5dee5'
  })

  const rect = new fabric.Rect({
    left: 50.top: 50.height: 20.width: 20.fill: 'green'
  })

  const circle = new fabric.Circle({
    left: 80.top: 80.radius: 40.fill: "red"
  })

  canvas.add(rect, circle)

  console.log('toPng', canvas.toDataURL('png')) PNG (base64)
  canvas.requestRenderAll()
}

onMounted(() = > {
  init()
})
</script>
Copy the code

You can output PNG images using Canvas.todataURL (‘ PNG ‘). But this may break the canvas rendering, so the following canvas.requestrenderAll () will be executed later.


You can copy this to your browser address and open it

data:image/png; base64,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 AAASUVORK5CYII=Copy the code


Output SVG

<template>
  <div>
    <canvas id="canvas" width="200" height="200" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  // Initialize the canvas
  const canvas = new fabric.Canvas('canvas', {
    backgroundColor: '#a5dee5'
  })

  const rect = new fabric.Rect({
    left: 50.top: 50.height: 20.width: 20.fill: 'green'
  })

  const circle = new fabric.Circle({
    left: 80.top: 80.radius: 40.fill: "red"
  })

  canvas.add(rect, circle)

  console.log(canvas.toSVG()) / / output SVG
}

onMounted(() = > {
  init()
})
</script>
Copy the code

Exporting SVG is easy, just call Canvas.tosvg ().


Output:


      
<! DOCTYPEsvg PUBLIC "- / / / / W3C DTD SVG 1.1 / / EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="200" height="200" viewBox="0 0 200 200" xml:space="preserve">
<desc>Created with Fabric. Js 4.6.0</desc>
<defs>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="#a5dee5"></rect>
<g transform=Matrix (1 0 0 1 60.5 60.5)  >
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; The fill: RGB (0128, 0); fill-rule: nonzero; opacity: 1;"  x="To 10" y="To 10" rx="0" ry="0" width="20" height="20" />
</g>
<g transform="Matrix (1 0 0 1 120.5 120.5)"  >
<circle style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; The fill: RGB (0, 255); fill-rule: nonzero; opacity: 1;"  cx="0" cy="0" r="40" />
</g>
</svg>
Copy the code








deserialization

🎁 Online preview of this section case – deserialization

🎁 This section code repository


Deserialization is rendering JSON data onto a canvas.

Usually the data requested from the background is rendered to the canvas.

<template>
  <div>
    <canvas id="canvas" width="200" height="200" style="border: 1px solid #ccc;"></canvas>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  const str = '{" version ":" 4.6.0 ", "objects" : [{" type ":" the rect ", "version" : "4.6.0", "originX" : "left", "originY" : "top", "left" : 50, "top" : 50, "wid th":20,"height":20,"fill":"green","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeDas hOffset":0,"strokeLineJoin":"miter","strokeUniform":false,"strokeMiterLimit":4,"scaleX":1,"scaleY":1,"angle":0,"flipX":f alse,"flipY":false,"opacity":1,"shadow":null,"visible":true,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill GlobalCompositeOperation ", ", "the source - over", "skewX" : 0, "skewY" : 0, "rx" : 0, "ry" : 0}, {" type ":" circle ", "version" : "4.6.0", "the origin X":"left","originY":"top","left":80,"top":80,"width":80,"height":80,"fill":"red","stroke":null,"strokeWidth":1,"strokeDa shArray":null,"strokeLineCap":"butt","strokeDashOffset":0,"strokeLineJoin":"miter","strokeUniform":false,"strokeMiterLim it":4,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"backgroundCo lor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","skewX":0,"skewY":0,"radius":4 0, "startAngle" : 0, "endAngle" : 6.283185307179586}], "background" : "# DDD"} '

  // Initialize the canvas
  const canvas = new fabric.Canvas('canvas')

  // deserialize
  canvas.loadFromJSON(str)
}

onMounted(() = > {
  init()
})
</script>
Copy the code


You can deserialize it using canvas.loadFromjson (), passing in a JSON-formatted string.

The STR in this example holds a fabric.js export of data.








Collect = Got it

Like = mastery