请指导我修改Fabricjs以为Rotation添加自定义图标。
我得到了一些答案但是效果不好。
请告诉我更改特定轮播图标的代码。
答案 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 .... ';