How can i change the rotation icon in fabricjs

前端 未结 7 1936
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-03 03:45

Please guide me to modify Fabricjs to add custom icon for Rotation.

I get some of the answers but it is not working fine.

Please let me know the code to chan

相关标签:
7条回答
  • 2021-01-03 04:17

    Change fabric object prototype "drawControls" like this.

    Here is an example and JSFiddle:

    fabric.Object.prototype.drawControls = function (ctx) {
        if (!this.hasControls) return this;
    
    
        var size = this.cornerSize,
            size2 = size / 2,
            strokeWidth2 = ~~(this.strokeWidth / 2), // half strokeWidth rounded down
            left = -(this.width / 2),
            top = -(this.height / 2),
            paddingX = this.padding / this.scaleX,
            paddingY = this.padding / this.scaleY,
            scaleOffsetY = size2 / this.scaleY,
            scaleOffsetX = size2 / this.scaleX,
            scaleOffsetSizeX = (size2 - size) / this.scaleX,
            scaleOffsetSizeY = (size2 - size) / this.scaleY,
            height = this.height,
            width = this.width,
            methodName = this.transparentCorners ? 'strokeRect' : 'fillRect';
    
        ctx.save();
    
        ctx.lineWidth = 1 / Math.max(this.scaleX, this.scaleY);
    
        ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
        ctx.strokeStyle = ctx.fillStyle = this.cornerColor;
    
        // top-left
        this._drawControl('tl', ctx, methodName,
            left - scaleOffsetX - strokeWidth2 - paddingX,
            top - scaleOffsetY - strokeWidth2 - paddingY);
    
        // top-right
        this._drawControl('tr', ctx, methodName,
            left + width - scaleOffsetX + strokeWidth2 + paddingX,
            top - scaleOffsetY - strokeWidth2 - paddingY);
    
        // bottom-left
        this._drawControl('bl', ctx, methodName,
            left - scaleOffsetX - strokeWidth2 - paddingX,
            top + height + scaleOffsetSizeY + strokeWidth2 + paddingY);
    
        // bottom-right
        this._drawControl('br', ctx, methodName,
            left + width + scaleOffsetSizeX + strokeWidth2 + paddingX,
            top + height + scaleOffsetSizeY + strokeWidth2 + paddingY);
    
        if (!this.get('lockUniScaling')) {
    
            // middle-top
            this._drawControl('mt', ctx, methodName,
                left + width / 2 - scaleOffsetX,
                top - scaleOffsetY - strokeWidth2 - paddingY);
    
            // middle-bottom
            this._drawControl('mb', ctx, methodName,
                left + width / 2 - scaleOffsetX,
                top + height + scaleOffsetSizeY + strokeWidth2 + paddingY);
    
            // middle-right
            this._drawControl('mr', ctx, methodName,
                left + width + scaleOffsetSizeX + strokeWidth2 + paddingX,
                top + height / 2 - scaleOffsetY);
    
            // middle-left
            this._drawControl('ml', ctx, methodName,
                left - scaleOffsetX - strokeWidth2 - paddingX,
                top + height / 2 - scaleOffsetY);
        }
    
        // middle-top-rotate
        if (this.hasRotatingPoint) {
            /*
             We dont need old corner for rotate :)
    
             this._drawControl('mtr', ctx, methodName,
             left + width/2 - scaleOffsetX,
             this.flipY
             ? (top + height + (this.rotatingPointOffset / this.scaleY) - this.cornerSize/this.scaleX/2 + strokeWidth2 + paddingY)
             : (top - (this.rotatingPointOffset / this.scaleY) - this.cornerSize/this.scaleY/2 - strokeWidth2 - paddingY));
    
             Draw rotate custom icon
             */
            var rotate = new Image(), rotateLeft, rotateTop;
            rotate.src = 'http://www.navifun.net/files/pins/tiny/Arrow-Rotate-Clockwise.png';
    
            rotateLeft = left + width / 2 - scaleOffsetX;
            rotateTop = this.flipY
                ? (top + height + (this.rotatingPointOffset / this.scaleY) - this.cornerSize / this.scaleX / 2 + strokeWidth2 + paddingY)
                : (top - (this.rotatingPointOffset / this.scaleY) - this.cornerSize / this.scaleY / 2 - strokeWidth2 - paddingY);
    
            ctx.drawImage(rotate, rotateLeft, rotateTop, size / this.scaleX, size / this.scaleY);
    
    
        }
    
        ctx.restore();
    
        return this;
    };
    
    0 讨论(0)
  • 2021-01-03 04:17

    This code works in Edge ,Chrome , FireFox, Try this, or You can copy the function from core js library file and then you can replace the ctx.drawImage function

     fabric.Object.prototype.drawControls = function (ctx) {
                if (!this.hasControls) {
                    return this;
                }
                var wh = this._calculateCurrentDimensions(), width = wh.x, height = wh.y, scaleOffset = this.cornerSize, left = -(width + scaleOffset) / 2, top = -(height + scaleOffset) / 2, methodName = this.transparentCorners ? "stroke" : "fill";
                ctx.save();
                ctx.strokeStyle = ctx.fillStyle = this.cornerColor;
                if (!this.transparentCorners) {
                    ctx.strokeStyle = this.cornerStrokeColor;
                }
                this._setLineDash(ctx, this.cornerDashArray, null);
                this._drawControl("tl", ctx, methodName, left, top);
                this._drawControl("tr", ctx, methodName, left + width, top);
                this._drawControl("bl", ctx, methodName, left, top + height);
                this._drawControl("br", ctx, methodName, left + width, top + height);
                if (!this.get("lockUniScaling")) {
                    this._drawControl("mt", ctx, methodName, left + width / 2, top);
                    this._drawControl("mb", ctx, methodName, left + width / 2, top + height);
                    this._drawControl("mr", ctx, methodName, left + width, top + height / 2);
                    this._drawControl("ml", ctx, methodName, left, top + height / 2);
                }
                if (this.hasRotatingPoint) {
                    this._drawControl("mtr", ctx, methodName, left + width / 2, top - this.rotatingPointOffset);
                    var rotate = new Image(), rotateLeft, rotateTop;
                    rotate.src = rotate_icon;
                    rotateLeft = left + width / 2;
                    rotateTop = top - this.rotatingPointOffset;
                    ctx.drawImage(rotate, rotateLeft-3, rotateTop-1, 18, 18);
    
                }
                ctx.restore();
                return this;
            };
    
    0 讨论(0)
  • 2021-01-03 04:23

    With the release of v4.0 in August of 2020, Fabric.js now includes a complete control customization system which makes styling the rotate control quite easy.

    var canvas = new fabric.Canvas('c');
    // set your icon here as a base64 string
    var rotateIcon = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTEyIDZ2M2w0LTQtNC00djNjLTQuNDIgMC04IDMuNTgtOCA4IDAgMS41Ny40NiAzLjAzIDEuMjQgNC4yNkw2LjcgMTQuOGMtLjQ1LS44My0uNy0xLjc5LS43LTIuOCAwLTMuMzEgMi42OS02IDYtNnptNi43NiAxLjc0TDE3LjMgOS4yYy40NC44NC43IDEuNzkuNyAyLjggMCAzLjMxLTIuNjkgNi02IDZ2LTNsLTQgNCA0IDR2LTNjNC40MiAwIDgtMy41OCA4LTggMC0xLjU3LS40Ni0zLjAzLTEuMjQtNC4yNnoiLz48L3N2Zz4=";
    var img = document.createElement('img');
    img.src = rotateIcon;
    
    // here's where your custom rotation control is defined
    // by changing the values you can customize the location, size, look, and behavior of the control
    fabric.Object.prototype.controls.mtr = new fabric.Control({
      x: 0,
      y: -0.5,
      offsetY: -40,
      cursorStyle: 'crosshair',
      actionHandler: fabric.controlsUtils.rotationWithSnapping,
      actionName: 'rotate',
      render: renderIcon,
      cornerSize: 28,
      withConnection: true
    });
    
    // here's where the render action for the control is defined
    function renderIcon(ctx, left, top, styleOverride, fabricObject) {
      var size = this.cornerSize;
      ctx.save();
      ctx.translate(left, top);
      ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle));
      ctx.drawImage(img, -size / 2, -size / 2, size, size);
      ctx.restore();
    }
    
    var rect = new fabric.Rect({
      left: 50,
      top: 70,
      fill: 'red',
      width: 200,
      height: 100,
      objectCaching: false,
      stroke: 'blue',
      strokeWidth: 4,
    });
    
    canvas.add(rect);
    canvas.setActiveObject(rect);
    <script src="https://unpkg.com/fabric@4.0.0/dist/fabric.js"></script>
    <canvas id="c" width="400" height="250" style="border:1px solid #ccc"></canvas>

    0 讨论(0)
  • 2021-01-03 04:26

    @hlozancic's answer overrides a big important part of the prototype. Monkey patching libraries maintained by a community doesn't sit well with me, since the code in those methods could change (and, in fact drawControls has changed since July 2nd), without my knowing. Here is an alternative that I prefer:

    var _original = fabric.Object.prototype._drawControl;
    fabric.Object.prototype._drawControl = function(control, ctx, methodName, left, top) {
      var size = this.cornerSize;
    
      if (this.canvas.hasControlCallback && this.canvas.hasControlCallback[control]) {
        this.canvas.controlCallback[control](ctx, left, top, size);
      } else {
        _original.call(this, control, ctx, methodName, left, top);
      }
    };
    
    /* then, when instantiating your fabric canvas  */
    
    var canvas = new fabric.Canvas();
    
    /* callbacks for drawing the controls */
    canvas.hasControlCallback = {
        mtr: true
    };
    
    canvas.controlCallback = {
        mtr: function mtrControlCallback (ctx, left, top, size) {
            var image = new Image(), x, y;
    
            image.src = 'http://www.navifun.net/files/pins/tiny/Arrow-Rotate-Clockwise.png';
            x = left - image.width/2 + size/2;
            y = top - image.height/2 + size/2;
    
            ctx.drawImage(image, x, y);
        }
    };
    

    Apologies for not providing a fiddle, and please be aware of the date of this writing.

    0 讨论(0)
  • 2021-01-03 04:26

    the problem with image not showing until you move is because image load is asynchronous. Inline it with data url:

    image.src = 'data:image/png;base64 .... ';
    
    0 讨论(0)
  • 2021-01-03 04:35

    For fabricjs above 1.6.6 changing function object prototype drawControls, small changes on hasRotation condition, result can be seen this JSFidle

    fabric.Object.prototype.drawControls = function (ctx) {
    
      if (!this.hasControls) {
        return this;
      }
    
      var wh = this._calculateCurrentDimensions(),
      width = wh.x,
      height = wh.y,
      scaleOffset = this.cornerSize,
      left = -(width + scaleOffset) / 2,
      top = -(height + scaleOffset) / 2,
      methodName = this.transparentCorners ? 'stroke' : 'fill';
    
      ctx.save();
      ctx.strokeStyle = ctx.fillStyle = this.cornerColor;
      if (!this.transparentCorners) {
        ctx.strokeStyle = this.cornerStrokeColor;
      }
     this._setLineDash(ctx, this.cornerDashArray, null);
    
      // top-left
     this._drawControl('tl', ctx, methodName,left,top);
    
     // top-right
    this._drawControl('tr', ctx, methodName, left + width,top);
    
    // bottom-left
    this._drawControl('bl', ctx, methodName,left, top + height);
    
    // bottom-right
    this._drawControl('br', ctx, methodName,left + width,top + height);
    
    if (!this.get('lockUniScaling')) {
    
    // middle-top
    this._drawControl('mt', ctx, methodName,
      left + width / 2,
      top);
    
    // middle-bottom
    this._drawControl('mb', ctx, methodName,
      left + width / 2,
      top + height);
    
    // middle-right
    this._drawControl('mr', ctx, methodName,
      left + width,
      top + height / 2);
    
    // middle-left
    this._drawControl('ml', ctx, methodName,
      left,
      top + height / 2);
    }
    
    // middle-top-rotate
    if (this.hasRotatingPoint) {
      var rotate = new Image(), rotateLeft, rotateTop;
      rotate.src = 'http://localhost:8000/images/toolbar/close.svg';
      rotateLeft = left + width / 2;
      rotateTop = top - this.rotatingPointOffset;
      ctx.drawImage(rotate, rotateLeft, rotateTop, 10, 15);
    }
    
    ctx.restore();
    
    return this;
    
    }
    
    0 讨论(0)
提交回复
热议问题