javascriptangularfabricjsangular18

How to prevent the border radius from disortion when decreasing the height?


Steps To Reproduce

  1. Create a fabric. js Rectangle Object with a fixed width and height.
  2. Apply a border-radius to the rectangle.
  3. Decrease the height of the rectangle significantly (e.g., reduce it to a value much smaller than the width).
  4. Observe the distorted appearance of the border-radius, which may look uneven or visually incorrect, similar to the issue shown in the image.

Expected Behavior

The rectangle's border-radius should remain proportional and smoothly rounded, regardless of the height.

Actual Behavior

The border-radius appears distorted and behaves unexpectedly when the height of the rectangle is decreased.

Code :

       const canvas = new fabric.Canvas('canvas');
        let canvasWidth = 640;
        let canvasHeight = 640;

        canvas.setWidth(canvasWidth);
        canvas.setHeight(canvasHeight);

      const rect = new fabric.Rect({
            left: 145, // Center the rectangle within the canvas
            top: 145,  // Center the rectangle within the canvas
            fill: 'blue',
            width: 350,
            height: 350,
            rx: 20, // Horizontal border radius
            ry: 20  // Vertical border radius
        });

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

        canvas.renderAll();
        

JSFiddle

Version Info :

image

image


Solution

  • UPDATE:

    To solve the jitter issues, you can debounce the method which is explained, below, we can use JS to do this.

    function debounce(func, timeout = 300){
      let timer;
      return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => { func.apply(this, args); }, timeout);
      };
    }
    function action(){
      this.set({
        width: this.width * this.scaleX,
        height: this.height * this.scaleY,
        scaleX: 1,
        scaleY: 1,
      });
    }
    const onScale = debounce(() => action());
    
    rect.on("scaling", function () {
      onScale();
    }) 
    

    const canvas = new fabric.Canvas("canvas")
    let canvasWidth = 640
    let canvasHeight = 640
    
    canvas.setWidth(canvasWidth)
    canvas.setHeight(canvasHeight)
    
    const rect = new fabric.Rect({
      left: 145, // Center the rectangle within the canvas
      top: 145, // Center the rectangle within the canvas
      fill: "blue",
      width: 350,
      height: 350,
      rx: 20, // Horizontal border radius
      ry: 20, // Vertical border radius
      objectCaching: false,
    })
    
        function debounce(func, timeout = 300){
          let timer;
          return (...args) => {
            clearTimeout(timer);
            timer = setTimeout(() => { func.apply(this, args); }, timeout);
          };
        }
        function action(){
          this.set({
            width: this.width * this.scaleX,
            height: this.height * this.scaleY,
            scaleX: 1,
            scaleY: 1,
          });
        }
        const onScale = debounce(() => action());
    
        rect.on("scaling", function () {
          onScale();
        }) 
    
    // Add rectangle to the canvas
    canvas.add(rect)
    
    canvas.renderAll()
    <!DOCTYPE html>
    <html>
    
    <head>
        <title>Fabric.js Adjustable Dashed Line</title>
        <!-- Using Fabric.js version 6.4.0 -->
        <script src="https://cdn.jsdelivr.net/npm/fabric@6.4.0/dist/index.min.js"></script>
    </head>
    
    <body>
        <canvas id="canvas"></canvas>
    </body>
    
    </html>

    You can use the rectangle scaling event to update the width and height so that the scaling is set to 1 and the rectangle height and width are updated.

    const canvas = new fabric.Canvas("canvas")
    let canvasWidth = 640
    let canvasHeight = 640
    
    canvas.setWidth(canvasWidth)
    canvas.setHeight(canvasHeight)
    
    const rect = new fabric.Rect({
      left: 145, // Center the rectangle within the canvas
      top: 145, // Center the rectangle within the canvas
      fill: "blue",
      width: 350,
      height: 350,
      rx: 20, // Horizontal border radius
      ry: 20, // Vertical border radius
      objectCaching: false,
    })
    
    rect.on("scaling", function () {
      this.set({
        width: this.width * this.scaleX,
        height: this.height * this.scaleY,
        scaleX: 1,
        scaleY: 1,
      })
    })
    
    // Add rectangle to the canvas
    canvas.add(rect)
    
    canvas.renderAll()
    <!DOCTYPE html>
    <html>
    
    <head>
        <title>Fabric.js Adjustable Dashed Line</title>
        <!-- Using Fabric.js version 6.4.0 -->
        <script src="https://cdn.jsdelivr.net/npm/fabric@6.4.0/dist/index.min.js"></script>
    </head>
    
    <body>
        <canvas id="canvas"></canvas>
    </body>
    
    </html>