我想知道是否有一种简单的方法来添加删除,带到前面,带回来 功能到现有的 fabric.js 对象控件。
目前我只能点击会删除对象的按钮,然后将其带到前面等等。
我正在寻找能够按下对象上的X(在右上角)并删除对象的解决方案。
我想这将与覆盖,包装或子类化现有控件对象有关。
也许我已经监督了一些事情并且有一个简单的解决方案?请不要Div Wrapper。
答案 0 :(得分:10)
Fabric.js不提供向对象添加控件的任何简单方法。 如果要创建自己的控件,则必须覆盖Object类,特别是:
drawControls
,以绘制自定义按钮_setCornerCoords
和_findTargetCorner
__onMouseDown
你不需要照顾' undrawing'控件,因为取消选择对象时将重新渲染整个画布。
我希望这会有所帮助,祝你好运:)。
答案 1 :(得分:5)
我通过定位html元素实现了它
canvas.on('object:selected',function(e){
jQuery(".deleteBtn").remove();
var btnLeft = e.target.oCoords.mt.x;
var btnTop = e.target.oCoords.mt.y - 25;
var widthadjust=e.target.width/2;
btnLeft=widthadjust+btnLeft-10;
var deleteBtn = '<p" class="deleteBtn" title="Delete" style="position:absolute;top:'+btnTop+'px;left:'+btnLeft+'px;cursor:pointer;" title="Remove object">✕</p>';
jQuery(".canvas-container").append(deleteBtn);
//.canvas-container is the parent div to the canvas positioned relative via CSS
});
canvas.on('mouse:down',function(e){
if(canvas.getActiveObject())
{
}
else
{
jQuery(".deleteBtn").remove();
}
});
canvas.on('object:modified',function(e){
jQuery(".deleteBtn").remove();
var btnLeft = e.target.oCoords.mt.x;
var btnTop = e.target.oCoords.mt.y - 25;
var widthadjust=e.target.width/2;
btnLeft=widthadjust+btnLeft-10;
var deleteBtn = '<p" class="deleteBtn" title="Delete" style="position:absolute;top:'+btnTop+'px;left:'+btnLeft+'px;cursor:pointer;" title="Remove object">✕</p>';
jQuery(".canvas-container").append(deleteBtn);
//.canvas-container is the parent div to the canvas positioned relative via CSS
});
//THE DELETE BUTTON CLICK EVENT
jQuery(document).on('click',".deleteBtn",function(){
if(canvas.getActiveObject())
{
canvas.remove(canvas.getActiveObject());
//this would remove the currently active object on stage,
jQuery(this).remove();
jQuery(".deleteBtn").remove();
}
})
答案 2 :(得分:2)
您可以尝试使用html按钮。看一下这个例子:
http://fabricjs.com/interaction-with-objects-outside-canvas/
以下是代码示例:
(function() {
var canvas = this.__canvas = new fabric.Canvas('c');
fabric.Object.prototype.transparentCorners = false;
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
fabric.Canvas.prototype.getAbsoluteCoords = function(object) {
return {
left: object.left + this._offset.left,
top: object.top + this._offset.top
};
}
var btn = document.getElementById('inline-btn'),
btnWidth = 85,
btnHeight = 18;
function positionBtn(obj) {
var absCoords = canvas.getAbsoluteCoords(obj);
btn.style.left = (absCoords.left - btnWidth / 2) + 'px';
btn.style.top = (absCoords.top - btnHeight / 2) + 'px';
}
fabric.Image.fromURL('../lib/pug.jpg', function(img) {
canvas.add(img.set({ left: 250, top: 250, angle: 30 }).scale(0.25));
img.on('moving', function() { positionBtn(img) });
positionBtn(img);
});
})();
答案 3 :(得分:2)
我相信带有dom元素的解决方案并不是那么稳定,但如果满足您的需求则可以, 我还需要将默认对象的角落按钮更改为我的Web应用程序的自定义按钮。 我用,
所以你必须改变两件事才能成功:
1。更改私人功能&#39; _drawControl&#39;来自fabric.js文件。这是关于13367号线(在我的fabric.js上)。在该功能结构上绘制对象的默认cornet按钮并在seleced上显示它们。 我们可以轻松地将png更改为我们的自定义。
下面是我更改的_drawControl(fabric.js):
_drawControl: function(control, ctx, methodName, left, top, flipiX, flipiY) {
var sizeX = this.cornerSize / this.scaleX,
sizeY = this.cornerSize / this.scaleY;
if (this.isControlVisible(control)) {
isVML || this.transparentCorners || ctx.clearRect(left, top, sizeX, sizeY);
var SelectedIconImage = new Image();
var lx='';
var ly='';
var n='';
switch (control)
{
case 'tl':
if (flipiY) { ly='b'; } else { ly = 't'; }
if (flipiX) { lx='r'; } else { lx = 'l'; }
break;
case 'tr':
if (flipiY) { ly='b'; } else { ly = 't'; }
if (flipiX) { lx='l'; } else { lx = 'r'; }
break;
case 'bl':
if (flipiY) { ly='t'; } else { ly = 'b'; }
if (flipiX) { lx='r'; } else { lx = 'l'; }
break;
case 'br':
if (flipiY) { ly='t'; } else { ly = 'b'; }
if (flipiX) { lx='l'; } else { lx = 'r'; }
break;
default:
ly=control.substr(0, 1);
lx=control.substr(1, 1);
break;
}
control=ly+lx;
switch (control)
{
case 'tl':
//my custom png for the object's top left corner
SelectedIconImage.src = 'assets/img/icons/draw_control/icon_rotate.png';
break;
case 'tr':
if (flipiX && !flipiY) { n='2'; }
if (!flipiX && flipiY) { n='3'; }
if (flipiX && flipiY) { n='4'; }
//my custom png for the object's top right corner
SelectedIconImage.src = 'assets/img/icons/draw_control/icon_delete.png';
break;
case 'mt':
SelectedIconImage.src = //add your png here if you want middle top custom image;
break;
case 'bl':
if (flipiY) { n='2'; }
SelectedIconImage.src = //add your png here if you want bottom left corner custom image;
break;
case 'br':
if (flipiX || flipiY) { n='2'; }
if (flipiX && flipiY) { n=''; }
//my custom png for the object's bottom right corner
SelectedIconImage.src = 'assets/img/icons/draw_control/icon_settings.png';
break;
case 'mb':
SelectedIconImage.src = //middle bottom png here ;
break;
case 'ml':
SelectedIconImage.src = 'assets/img/icons/draw_control/icono_escala_horizontal'+n+'.jpg';
break;
case 'mr':
SelectedIconImage.src = //middle right png here;
break;
default:
ctx[methodName](left, top, sizeX, sizeY);
break;
}
// keep middle buttons size fixed
if (control == 'tl' || control == 'tr' || control == 'bl' || control == 'br'
|| control == 'mt' || control == 'mb' || control == 'ml' || control == 'mr')
{
sizeX = 19;
sizeY = 19;
ctx.drawImage(SelectedIconImage, left, top, sizeX, sizeY);
}
try {
ctx.drawImage(SelectedIconImage, left, top, sizeX, sizeY);
} catch (e) {
if (e.name != "NS_ERROR_NOT_AVAILABLE") {
throw e;
}
}
}
},
正如前面提到的 Toon Nelissen ,我在fabric.Canvas.prototype.__onMouseDown
功能旁边,并控制我的自定义按钮。
fabric.Canvas.prototype.__onMouseDown = function (e) {
// accept only left clicks
var isLeftClick = 'which' in e ? e.which === 1 : e.button === 1;
if (!isLeftClick && !fabric.isTouchSupported) {
return;
}
if (this.isDrawingMode) {
this._onMouseDownInDrawingMode(e);
return;
}
// ignore if some object is being transformed at this moment
if (this._currentTransform) {
return;
}
var target = this.findTarget(e),
pointer = this.getPointer(e, true);
//if user clicked on the top right corner image
if (target && target.__corner === 'tr') {
//my code goes here
}
} else {
// save pointer for check in __onMouseUp event
this._previousPointer = pointer;
var shouldRender = this._shouldRender(target, pointer),
shouldGroup = this._shouldGroup(e, target);
if (this._shouldClearSelection(e, target)) {
this._clearSelection(e, target, pointer);
} else if (shouldGroup) {
this._handleGrouping(e, target);
target = this.getActiveGroup();
}
if (target && target.selectable && !shouldGroup) {
this._beforeTransform(e, target);
this._setupCurrentTransform(e, target);
}
// we must renderAll so that active image is placed on the top canvas
shouldRender && this.renderAll();
this.fire('mouse:down', { target: target, e: e });
target && target.fire('mousedown', { e: e });
}
};
对于其他角落,我们还要编写相应的片段(在__onMouseDown内):
//if user clicked on the bottom right corner image
if (target && target.__corner === 'br') {
//my code here
}else{
//the same as 'tr'
}
//if user clicked on the top left corner image
if (target && target.__corner === 'tl') {
//my code here
}else{
//the same as 'tr'
}
//if user clicked on the bottom left corner image
if (target && target.__corner === 'bl') {
//my code here
}else{
//the same as 'tr'
}
下面是我的网络应用程序自定义图像的屏幕截图
答案 4 :(得分:1)
您可以覆盖__onMouseDown函数,例如这样。
目标对象包含__corner元素target.__corner
检查这是否是&#39; tr&#39; (右上角)并删除activeObject
if (target.__corner === 'tr') {
if(canvas.getActiveObject()){
canvas.remove(canvas.getActiveObject());
}
}
完整代码:
fabric.Canvas.prototype.__onMouseDown = function (e) {
// accept only left clicks
var isLeftClick = 'which' in e ? e.which === 1 : e.button === 1;
if (!isLeftClick && !fabric.isTouchSupported) {
return;
}
if (this.isDrawingMode) {
this._onMouseDownInDrawingMode(e);
return;
}
// ignore if some object is being transformed at this moment
if (this._currentTransform) {
return;
}
var target = this.findTarget(e),
pointer = this.getPointer(e, true);
if (target && target.__corner === 'tr') {
if(this.getActiveObject()){
this.remove(this.getActiveObject());
}
} else {
// save pointer for check in __onMouseUp event
this._previousPointer = pointer;
var shouldRender = this._shouldRender(target, pointer),
shouldGroup = this._shouldGroup(e, target);
if (this._shouldClearSelection(e, target)) {
this._clearSelection(e, target, pointer);
} else if (shouldGroup) {
this._handleGrouping(e, target);
target = this.getActiveGroup();
}
if (target && target.selectable && !shouldGroup) {
this._beforeTransform(e, target);
this._setupCurrentTransform(e, target);
}
// we must renderAll so that active image is placed on the top canvas
shouldRender && this.renderAll();
this.fire('mouse:down', { target: target, e: e });
target && target.fire('mousedown', { e: e });
}
};