Alien13
Alien13

Reputation: 618

Fabric JS how to set border radius on bounding box of selected objects

Is it possible to change the border radius of a bounding box of a selected item? I have read through the documentation of the possible attributes that can be attributed to an object and haven't found anything that specifies the changing of the border radius of an object's bounding box. Is there perhaps an solution through CSS this can be done?

Upvotes: 1

Views: 2075

Answers (1)

melchiar
melchiar

Reputation: 2862

Here's a drop-in replacement for the fabric.Object.prototype.drawBorders method that handles the drawing of selection borders. I've extended it to use the property selectionRadius to determine the amount of border radius to use in the selection box.

enter image description here

var canvas = new fabric.Canvas("canvas");

canvas.add(new fabric.Rect({
  width: 150,
  height: 100,
  left: 25,
  top: 25,
  fill: 'lightgreen',
  strokeWidth: 0,
  padding: 20,
  selectionRadius: 20,
  borderColor: 'red'
}));

fabric.Object.prototype.drawBorders = function(ctx, styleOverride) {
  styleOverride = styleOverride || {};
  var wh = this._calculateCurrentDimensions(),
    strokeWidth = this.borderScaleFactor,
    width = wh.x + strokeWidth,
    height = wh.y + strokeWidth,
    hasControls = typeof styleOverride.hasControls !== 'undefined' ?
    styleOverride.hasControls : this.hasControls,
    shouldStroke = false;

  ctx.save();
  ctx.strokeStyle = styleOverride.borderColor || this.borderColor;
  this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray, null);

  //start custom draw method with rounded corners
  var rx = this.selectionRadius ? Math.min(this.selectionRadius, width / 2) : 0,
    ry = this.selectionRadius ? Math.min(this.selectionRadius, height / 2) : 0,
    w = width,
    h = height,
    x = -width / 2,
    y = -height / 2,
    isRounded = rx !== 0 || ry !== 0,
    /* "magic number" for bezier approximations of arcs */
    k = 1 - 0.5522847498;
  ctx.beginPath();

  ctx.moveTo(x + rx, y);

  ctx.lineTo(x + w - rx, y);
  isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry);

  ctx.lineTo(x + w, y + h - ry);
  isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h);

  ctx.lineTo(x + rx, y + h);
  isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry);

  ctx.lineTo(x, y + ry);
  isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y);

  ctx.closePath();
  ctx.stroke();
  //end custom draw method with rounded corners


  if (hasControls) {
    ctx.beginPath();
    this.forEachControl(function(control, key, fabricObject) {
      // in this moment, the ctx is centered on the object.
      // width and height of the above function are the size of the bbox.
      if (control.withConnection && control.getVisibility(fabricObject, key)) {
        // reset movement for each control
        shouldStroke = true;
        ctx.moveTo(control.x * width, control.y * height);
        ctx.lineTo(
          control.x * width + control.offsetX,
          control.y * height + control.offsetY
        );
      }
    });
    if (shouldStroke) {
      ctx.stroke();
    }
  }
  ctx.restore();
  return this;
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.4.0/fabric.min.js"></script>
<canvas id="canvas" height="300" width="400"></canvas>

Upvotes: 2

Related Questions