如何更改fabricjs中的旋转图标

时间:2014-04-22 05:18:27

标签: javascript html5 fabricjs

请指导我修改Fabricjs以为Rotation添加自定义图标。

我得到了一些答案但是效果不好。

请告诉我更改特定轮播图标的代码。

7 个答案:

答案 0 :(得分:13)

更改布料对象原型" drawControls"像这样。

以下是一个示例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;
};

答案 1 :(得分:13)

@ hlozancic的回答覆盖了原型的一个重要部分。由社区维护的猴子修补库并不适合我,因为这些方法中的代码可能会发生变化(实际上drawControls自7月2日起已经发生变化),我不知道。这是我更喜欢的替代方案:

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);
    }
};

不提供小提琴的道歉,请注意撰写本文的日期。

答案 2 :(得分:3)

对于1.6以上的fabricjs更改函数对象原型drawControls,对hasRotation条件进行小的更改,结果可以看出这个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;

}

答案 3 :(得分:1)

此代码适用于Edge,Chrome,FireFox,试试这个或 您可以从核心js库文件中复制该函数,然后可以替换ctx.drawImage函数

 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;
        };

答案 4 :(得分:1)

随着2020年8月v4.0的发布,Fabric.js现在包括一个完整的控件自定义系统,使旋转控件的样式设计非常容易。

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>

答案 5 :(得分:0)

我知道这是一个非常古老的问题,但对于任何寻求更简单解决方案的人来说都是如此:

https://github.com/pixolith/fabricjs-customise-controls-extension

这个插件是最新的,对我来说非常适合。您不必覆盖结构js的内部逻辑,因此更安全。

答案 6 :(得分:-1)

在移动之前图像不显示的问题是因为图像加载是异步的。用数据网址内联它:

image.src = 'data:image/png;base64 .... ';