Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I calculate area of all text objects inside the canvas bounds using fabricjs?

I am working on a function that calculates the total area of text (using its' bounds, not the text itself) on the canvas as a percentage of the total canvas size. Currently, it only checks the size of all text objects on the canvas vs the total area of the canvas and doesn't account for any part of the text that may be clipping outside the canvas boundary.

I want to calculate the total area that is outside the boundary of the canvas and subtract that from the total area of text objects.

I am stuck with some of the math required for calculating this. These are the essential pieces of information required to perform this calculation:

  • The width and height of the canvas (px)
  • The width and height of the text object (px)
  • The "left" and "bottom" position of the object (px)

The calculation needs to determine, first of all, whether the object is actually outside the canvas bounds. It then needs to determine whether the "left" or "bottom" position are positive or negative.

Here is the code I have so far but I feel like I'm going the wrong way about it:

  getTextCoverage() : number {
    var objects = this.canvas.getObjects();
    var canvasArea = this.canvasSize.width * this.canvasSize.height;
    var totalTextArea = 0;

// loop through all canvas objects
    for (var object of objects){
      if (object.text){
        // Check if the textbox is outside the canvas to the left or right
        var xOutsideCanvas = object.left + (object.width * object.scaleX) > object.width * object.scaleX ? 
          // If true the textbox is outside the canvas to the right
          this.canvas.width - (object.left + (object.width * object.scaleX)) : 
          // If false the textbox is outside the canvas to the left
          - this.canvas.width - (object.left + (object.width * object.scaleX));

        totalTextArea += (object.width * object.scaleX) * (object.height * object.scaleY);
        if(object.left + (object.width * object.scaleX) > this.canvas.width){
        }
      }
    }

    return ((totalTextArea / canvasArea) * 100) * 5;
  }
like image 787
Jeremy Avatar asked Nov 06 '19 10:11

Jeremy


1 Answers

I think you were on the right lines, I've modified your code slightly so that it's finding the minimum and maximum X/Y co-ordinates of each text object that are actually on the canvas. Then it's straightforward to calculate the area based on that. Oh, and no need to multiply again by the scaling factor when you're calculating the area.

  if (object.text) {
    var minX = Math.max(0, object.left);
    var minY = Math.max(0, object.top);
    var right = (object.left + (object.width * object.scaleX));
    var maxX = Math.min(right, canvas.width);
    var bottom = (object.top + (object.height * object.scaleY));
    var maxY = Math.min(bottom, canvas.height);

    totalTextArea += ((maxX - minX) * (maxY - minY));
  }
like image 111
John M Avatar answered Nov 20 '22 08:11

John M