Want to know moreFabric.jsPlay, pay attention to me, the first time to get the latest push




In this article

Before reading this article, you need to know what fabric.js is and how fabric.js creates rectangles.

If you do not meet the above two criteria, we recommend you read Fabric.js from Getting Started to ____.


I created the rectangle in fabric.js using the box selection operation.

In the next few articles I will write about how to freely draw circles, ovals, triangles, line segments, polylines, and polygons.


This article does not do anyCSSRelevant beautification, only to explain the realization of the principle.

The following figure shows the effect of this article.


With frameworks like fabric.js, versioning is important.

The version used for this article: fabric.js 4.6.0





The principle of

Core principles

The core of rectangle generated by “box selection” is 2 points:

  1. Click and lift the mouse to get the coordinates, that is, the start and end points.
  2. With the mouse up,1 pointThe obtained two coordinates compute the length, width, and position of the rectangle.


Mouse click: Canvas. on(‘mouse:down’, fn)

On (‘mouse:up’, fn)


Factors to consider

Understanding the core points above, the next thing you need to consider is the direction of the mouse frame selection.

  1. Select from the top left to bottom right box
  2. Select from the bottom right to the top left box
  3. Select from bottom left to top right
  4. Select from the upper right to the lower left box


These four conditions affect the length, width, and position of the resulting rectangle.


Generate rectangle code

new fabric.Rect({
    top: 0.// The top left corner of the rectangle is on the Y-axis
    left: 0.// The top left corner of the rectangle is in the X-axis position
    width: 100.// Width of rectangle
    height: 100.// Height of the rectangle
    fill: 'transparent'./ / fill color
    stroke: '# 000' // Border color
})
Copy the code


Let’s talk about the impact of each of these four actions.


fromUpper leftThe lower rightBox to choose

This situation is best handled.

The starting point is the upper left corner of the rectangle, and the ending point is the lower right corner of the rectangle.

The x and y coordinates of the start point are less than the end point, (the start point x is less than the end point x; Start point Y < end point y) :

  • Width of rectangle:End x-coordinate. - Start x-coordinate(You could say yesThe absolute value of the starting point x minus the ending point x).
  • Height of rectangle:End point y. - Start point y(You could say yesThe absolute value of the starting point y minus the ending point y).
  • The position of the upper left corner on the X-axis:The x-coordinate of the starting point
  • The position of the upper left corner on the Y-axis:The y-coordinate of the starting point


fromThe lower rightUpper leftBox to choose

Start point x > end point x; Start point y > end point y

  • Width:Starting point x - ending point x
  • High:Starting point y - ending point y
  • The coordinates of the upper left corner on the X-axis:End point x
  • The Y-axis coordinates of the upper left corner:End point y


fromThe lower leftThe upper rightBox to choose

Starting point x < ending point x; Start point y > end point y

  • Width:Absolute value of the starting point x minus the ending point y
  • High:Starting point y - ending point y
  • The coordinates of the upper left corner on the X-axis:The starting point xCompare the x coordinate, and take the smaller oneMath.minMethods).
  • The Y-axis coordinates of the upper left corner:End point yCompare the y-coordinate and take the smaller one.


fromThe upper rightThe lower leftBox to choose

Start point x > end point x; Our starting point y is less than our ending point y

  • Width:Starting point x - ending point x
  • High:The absolute value of the starting point y minus the ending point y
  • The coordinates of the upper left corner on the X-axis:End point xCompare the x coordinate, and take the smaller oneMath.minMethods).
  • The Y-axis coordinates of the upper left corner:The starting point for yCompare the y-coordinate and take the smaller one.


Conclusion the formula

After analyzing the above four cases, the formulas of these parameters are finally summarized.

I’ll call the start point downPoint and the end point upPoint.

Several parameters of the rectangle are calculated as follows:

new fabric.Rect({
    top: Math.min(downPoint.y, upPoint.y),
    left: Math.min(downPoint.x, upPoint.x),
    width: Math.abs(downPoint.x - upPoint.x),
    height: Math.abs(downPoint.y - upPoint.y),
    fill: 'transparent'.stroke: '# 000'
})
Copy the code


Math.min: Take the smaller of the two

Math.abs: Returns the absolute value

These two methods are provided by JS, if you do not understand the suggestion to Baidu.





implement

I’ve posted the code and comments implemented natively here.

If you want to know how to implement fabric.js free-drawing rectangles in Vue3, look it up in the code repository.

<! -- Toolbar -->
<div class="toolbar">
  <select onchange="typeChange(this.options[this.options.selectedIndex].value)">
    <option value="default">Default (box selected)</option>
    <option value="rect">rectangular</option>
  </select>
</div>

<! - canvas - >
<canvas id="canvas" width="800" height="800"></canvas>

<! Fabric.js -->
<script src="https://cdn.bootcdn.net/ajax/libs/fabric.js/460/fabric.js"></script>

<script>
let canvas = null // Canvas object

let currentType = 'default' / / the current operating mode (the default | | create rectangle)

let downPoint = null // The coordinates when the mouse is pressed
let upPoint = null // The coordinates when the mouse is released

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

  canvas.on('mouse:down', canvasMouseDown)   // Press the mouse over the canvas
  canvas.on('mouse:up', canvasMouseUp)       // Release the mouse over the canvas
}

// Canvas operation type switch
function typeChange(opt) {
  currentType = opt
  switch(opt) {
    case 'default': // Box mode by default
      canvas.selection = true // Allow box selection
      canvas.selectionColor = 'rgba (100, 100, 255, 0.3)' // Box fill color: translucent blue
      canvas.selectionBorderColor = 'rgba (255, 255, 255, 0.3)' // Select the frame frame color: translucent gray
      canvas.skipTargetFind = false // Allow selection
      break
    case 'rect': // Create rectangle pattern
      canvas.selectionColor = 'transparent' // Fill the box with transparent color
      canvas.selectionBorderColor = 'rgba (0, 0, 0, 0.2)' // Box border color: black with low opacity (looks gray)
      canvas.skipTargetFind = true // Disable the check
      break}}// Press the mouse over the canvas
function canvasMouseDown(e) {
  // Assign the current coordinates to downPoint with the left mouse button down. X: XXX, y: XXX} format
  downPoint = e.absolutePointer
}

// Release the mouse over the canvas
function canvasMouseUp(e) {
  // Execute the following code in rectangle mode
  if (currentType === 'rect') {
    // When you release the left mouse button, assign the current coordinates to upPoint
    upPoint = e.absolutePointer
    // Call the method that creates the rectangle
    createRect()
  }
}

// Create rectangle
function createRect() {
  // If you click and release the mouse, both are in the same coordinate point, no rectangle will be generated
  if (JSON.stringify(downPoint) === JSON.stringify(upPoint)) {
    return
  }

  // Create rectangle
  // Calculate the rectangle parameters.
  let top = Math.min(downPoint.y, upPoint.y)
  let left = Math.min(downPoint.x, upPoint.x)
  let width = Math.abs(downPoint.x - upPoint.x)
  let height = Math.abs(downPoint.y - upPoint.y)

  // Rectangle object
  const rect = new fabric.Rect({
    top,
    left,
    width,
    height,
    fill: 'transparent'.// Fill color: transparent
    stroke: '# 000' // Frame color: black
  })

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

  // Empty downPoint and upPoint after creating the rectangle. Of course, you don't have to do this.
  downPoint = null
  upPoint = null
}

// The page load lifecycle, where the canvas is initialized
window.onload = function() {
  initCanvas()
}
</script>
Copy the code





Code warehouse

  • ⭐ The code for the native version ****
  • ⭐Vue3 version code





Recommended reading

  • 👍 Fabric.js Custom Right-click Menu

  • 👍 Fabric.js from Getting Started to Expanding

  • 👍 4 Ways to Align Elements with Fabric.js (with transition animation)

  • 👍 Fabric.js Remove Elements (with transition animation)


Finally, don’t forget to follow the likes at 😊