V. Sambor
V. Sambor

Reputation: 13389

Fabric Js - change position of control corners

I have a fabric js rectangle and I would like to move the control squares inside the rectangle.

I don't know if this is possible in the version I'm using, I didn't found how to do this.

Note I am using fabric.js version: 2.4.6

Here is what I've tried:

      this._cropRect = new window.fabric.Rect({
        top: 0,
        left: 0,
        width: this.options.canvasWidth,
        height: this.options.canvasHeight,
        fill: 'red',
        strokeWidth: 0,
        lockRotation: true,
        lockScalingFlip: true,
        lockUniScaling: true,
        hasBorders: false,
        hasRotatingPoint: false,
        padding: -12,
        cornerColor: 'red',
        borderColor: 'red',
        cornerStroke: 10,
        borderScaleFactor: 2,
        cornerSize: CROP_CORNER_SIZE,
        borderOpacityWhenMoving: 1,
      })

      this._cropRect.set('globalCompositeOperation', 'destination-out')

      this._fabricCanvas.add(this._cropRect)
      this._fabricCanvas.setActiveObject(this._cropRect)
      this._fabricCanvas.requestRenderAll()

Here is the image of what I have now and what I want to achieve:

enter image description here

UPDATE:

I have created a jsfiddle: https://jsfiddle.net/t94ksgeq/

Upvotes: 1

Views: 1748

Answers (1)

Casper Kuethe
Casper Kuethe

Reputation: 1130

You could extend the draw function of the cropping rectangles.


cropRect.drawControls = function(t, e) {
    e = e || {};
    var i = this._calculateCurrentDimensions(),
        // Modified variable r and n
        r = i.x - this.cornerSize,
        n = i.y - this.cornerSize,
        s = e.cornerSize || this.cornerSize,
        o = -(r + s) / 2,
        a = -(n + s) / 2,
        h = void 0 !== e.transparentCorners ? e.transparentCorners : this.transparentCorners,
        c = void 0 !== e.hasRotatingPoint ? e.hasRotatingPoint : this.hasRotatingPoint,
        l = h ? "stroke" : "fill";
    return t.save(), t.strokeStyle = t.fillStyle = e.cornerColor || this.cornerColor, this.transparentCorners || (t.strokeStyle = e.cornerStrokeColor || this.cornerStrokeColor), this._setLineDash(t, e.cornerDashArray || this.cornerDashArray, null), this._drawControl("tl", t, l, o, a, e), this._drawControl("tr", t, l, o + r, a, e), this._drawControl("bl", t, l, o, a + n, e), this._drawControl("br", t, l, o + r, a + n, e), this.get("lockUniScaling") || (this._drawControl("mt", t, l, o + r / 2, a, e), this._drawControl("mb", t, l, o + r / 2, a + n, e), this._drawControl("mr", t, l, o + r, a + n / 2, e), this._drawControl("ml", t, l, o, a + n / 2, e)), c && this._drawControl("mtr", t, l, o + r / 2, a - this.rotatingPointOffset, e), t.restore(), this
}

in this code r and n represent the x and y values and I found that if you subtract the cornersize. The recetangles get drawn inside the image. Now the rectangles are exactly inside the the rectangle on the edge, but ofcourse you can modify it to your needs.

EDIT:

After further inspection I found that you can adjust the position of the resize controls in the _setCornerCoords function.

function degrees_to_radians(degrees) {
  var pi = Math.PI;
  return degrees * (pi/180);
}

cropRect._setCornerCoords = function () { 
    var t,
    e,
    i = this.oCoords,
    r = degrees_to_radians(45 - this.angle),
    n = .707106 * this.cornerSize,
    s = n * fabric.util.cos(r),
    o = n * fabric.util.sin(r);

    // Again this is setup to be the cornerSize, but this can be any number
    var p = this.cornerSize;
    var q = p / 2;

    for (var a in i) {
      t = i[a].x;
      e = i[a].y;
      
      // Check which kind of corner it is and translate it accordingly
      switch(a) {
        case "tl":
            t += q;
          e += q;
          break;
        case "tr":
          t -= q;
          e += q;
          break;
        case "br":
          t -= q;
          e -= q;
          break;
        case "bl":
          t += q;
          e -= q;
          break;
      }      
      
      i[a].corner = { 
        tl: { x: t - o,  y: e - s },
        tr: { x: t + s, y: e - o },
        bl: { x: t - s,  y: e + o },
        br: { x: t + o, y: e + s } 
      } 
    }
}

This enables the user to resize within the previously drawn corners. The resize may seem not aligned with the mouse position (hardly noticable in usage).

This is because you begin resizing not from the corner. And the resize function follows the difference in mouse position. And uses some different coordinates, but I was unable to find those.

Upvotes: 4

Related Questions