Пожалуйста, помогите мне изменить Fabricjs, чтобы добавить собственный значок для вращения.
Я получаю некоторые ответы, но это не работает нормально.
Пожалуйста, дайте мне знать код для изменения только определенного значка поворота.
Пожалуйста, помогите мне изменить Fabricjs, чтобы добавить собственный значок для вращения.
Я получаю некоторые ответы, но это не работает нормально.
Пожалуйста, дайте мне знать код для изменения только определенного значка поворота.
Для Fabricjs выше 1.6.6 изменение прототипа объекта функции 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;
}
Измените прототип объекта ткани «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;
};
Ответ @hlozancic переопределяет большую важную часть прототипа. Библиотеки исправлений Monkey, поддерживаемые сообществом, меня не устраивают, поскольку код в этих методах может измениться (и фактически drawControls
изменился со 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);
}
};
Приносим извинения за то, что не предоставили скрипку, и, пожалуйста, обратите внимание на дату написания этой статьи.
Этот код работает в 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.0 в августе 2020 года 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/[email protected]/dist/fabric.js"></script>
<canvas id="c" width="400" height="250" style="border:1px solid #ccc"></canvas>
Я знаю, что это довольно старый вопрос, но для тех, кто ищет более простое решение:
https://github.com/pixolith/fabricjs-customise-controls-extension
Этот плагин обновлен и отлично работает для меня. Вам не придется переопределять внутреннюю логику Fabric js, и поэтому ее использование безопаснее.
проблема с изображением, которое не отображается до тех пор, пока вы не переместитесь, заключается в том, что загрузка изображения является асинхронной. Вставьте его с URL-адресом данных:
image.src = 'data:image/png;base64 .... ';