In this article

This time I’m going to talk about 4 ways to “straighten out” elements, which is a scenario I’ve encountered in my work.

I don’t know whether “straighten” is the correct translation, but that’s what I’m going to call it!

Straighten: Rotate elements from their current Angle to 0, 90, 180, 270, etc., depending on distance.

[Definition of Baidu Baike]

Straighten, involve, is a transitive verb meaning “to straighten up; Make the… Rectification. Make the… Straight; Make the… To get better “, as an intransitive verb meaning “to become straight; Get better.


English class on behalf of the reminder ~


The effect is shown below





Release notes

Fabric.js version: 4.6.0





The relevant API

Fabric.js provides several apis to accomplish alignment:

  • canvas.straightenObject(object)
  • object.straighten()
  • canvas.fxStraightenObject(object)
  • object.fxStraighten()


Note that the use ofobject.straightenobject.fxStraightenThe screen will not update automatically after the elements are aligned (but it is already aligned)canvas.renderAll()And refresh the canvas API.

The official documentation doesn’t seem to specify this.


Of the above four apis, the ones with FX have transition animations.





The sample code

In the rest of the code, I’m going to use elements that I’ve defined in public variables.

If you need to get specified elements dynamically, you can use methods such as canvis.getobjects (), getActiveObject(), etc., depending on your business scenario.

None of these methods are the focus of this article, so let’s go back to the original purpose.


Method 1:canvas.straightenObject

StraightenObject This method allows us to pass in one argument. This parameter is the element Object (fabric.object) that you need to align.


Let me use a triangle as an example. The logic is written in the code comments.

<button onclick="straightenObject()">Straighten elements</button>
<canvas id="canvasBox" width="600" height="600"></canvas>

<! Fabric.js -->
<script src="https://cdn.bootcdn.net/ajax/libs/fabric.js/460/fabric.min.js"></script>
<script>
let canvas = null // Canvas object
let triangle = null // Triangle object

window.onload = function() {
  // Initialize the canvas
  canvas = new fabric.Canvas('canvasBox', {
    width: 400.height: 400
  })

  / / triangle
  triangle = new fabric.Triangle({
    top: 100.left: 100.width: 80.// The bottom length
    height: 100.// The distance from base to diagonal
    fill: 'blue'.angle: 30 // Rotated 30 degrees
  })
  
  // Add the rectangle to the canvas
  canvas.add(triangle)
}

/ / straighten
function straightenObject() {
  // Pass in the triangle object
  canvas.straightenObject(triangle)
}
</script>
Copy the code


Method 2:object.straighten

Straighten can also achieve canvas. StraightenObject straightening.

But Object.bound doesn’t automatically refresh the canvas, requiring methods like canvas.renderall ().

<! -- Omit some code -->

<script>
/ / straighten
function straightenObject() {
  // The triangle object calls the straighten method to straighten itself
  triangle.straighten()
  // The canvas needs to be refreshed
  canvas.renderAll()
}
</script>
Copy the code


Method 3:canvas.fxStraightenObject

The first two methods have no transition effect.

Then try with transition effects of API: canvas. FxStraightenObject.

And canvas straightenObject, canvas. FxStraightenObject Object also need to pass in a parameter (fabric) Object).

<button onclick="fxStraightenObject()">Straighten elements (transition animation)</button>
<canvas id="canvasBox" width="600" height="600"></canvas>

<! Fabric.js -->
<script src="https://cdn.bootcdn.net/ajax/libs/fabric.js/460/fabric.min.js"></script>
<script>
let canvas = null // Canvas object
let triangle = null // Triangle object

window.onload = function() {
  // Initialize the canvas
  canvas = new fabric.Canvas('canvasBox', {
    width: 400.height: 400
  })

  / / triangle
  triangle = new fabric.Triangle({
    top: 100.left: 100.width: 80.// The bottom length
    height: 100.// The distance from base to diagonal
    fill: 'blue'.angle: 30 // Rotated 30 degrees
  })
  
  // Add the rectangle to the canvas
  canvas.add(triangle)
}

/ / straighten
function fxStraightenObject() {
  // Pass in the triangle object
  canvas.fxStraightenObject(triangle)
}
</script>
Copy the code

Canvas. FxStraightenObject method does not need to use additional refresh the canvas.


Method 4:object.fxStraighten

Straighten with transition animation is also possible using Object. fxStraighten.

But Object. fxStraighten is a bit special in that it can also pass in a parameter, which is an object with two function fields in it.

  • onComplete: The callback function after the animation is complete
  • onChange: callback function during animation execution

The usage is shown below

<! -- Omit some code -->

<script>
/ / straighten
function fxStraightenObject() {
  // Pass in the triangle object
    triangle.fxStraighten({
    onChange() {
      canvas.renderAll()
    },
    onComplete() {
      canvas.renderAll()
    }
  })
}
</script>
Copy the code


A piece of my mind

  1. You can use this if you have a small number of elements to aligncanvas.straightenObjectcanvas.fxStraightenObject.
  2. If the number of elements is large, useobject.straightenPut all the elements in place, and then do it againcanvas.renderAll(), refresh once.
  3. If the number of elements is large, useobject.fxStraightenIf you do not need to perform any operations in the callback function, you can userequestAnimationFrameMethod of collective refresh.


The code in point 3 above

<button onclick="fxStraightenObject()">Straighten elements (transition animation)</button>
<canvas id="canvasBox" width="600" height="600"></canvas>
  
<script src="https://cdn.bootcdn.net/ajax/libs/fabric.js/460/fabric.js"></script>
<script>
let canvas = null // Canvas object
let triangle = null // Triangle object
let rect = null // Rectangle object

window.onload = function() {
  // Create a canvas with the element ID, which you can box on the canvas
  canvas = new fabric.Canvas('canvasBox', {
    width: 400.height: 400
  })

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

  / / rectangle
  rect = new fabric.Rect({
    top: 70.left: 200.width: 100./ / wide
    height: 30./ / high
    fill: 'orange'.angle: -40
  })
  
  // Add the rectangle to the canvas
  canvas.add(triangle, rect)
  renderAll()
}

// Refresh the canvas continuously
function renderAll() {
  canvas.renderAll()
  requestAnimationFrame(renderAll)
}

// Align (with transition animation)
function fxStraightenObject() {
  triangle.fxStraighten() // Align the triangle
  rect.fxStraighten() // Straighten the rectangle
}

</script>
Copy the code

This is just to give you an idea, and real development needs to be flexible depending on your business.





Code warehouse

  • Alignment elements native (with transition animation)
  • Alignment elements with Fabric in Vue3 (with transition animation)





Recommended reading

  • ⭐ Fabric.js from Getting Started to Expanding
  • ⭐ fabric.js 3 apis to Set canvas Width and Height
  • ⭐ Fabric.js Custom Right-click Menu