Fabric.js: Group-Selection 将某些对象的中心位置转换为 canvas 原点
Fabric.js: Group-Selection transforms certain objects' center position to canvas origin
在一个 angular 应用程序中,我用 Fabric.js 实现了一个简单的白板,它可以让用户绘制一些基本形状和手绘图。形状是空白和填充的圆形和矩形,以及一个基本的 UML 图模板,它们是两个彼此重叠的单个矩形。
当我select一个或多个对象时,所有矩形和圆实例的位置自动转换到canvas'原点,只留下select离子标记在原来的位置。奇怪的是,这不会发生在 UML 模板中,它最终也由两个简单的矩形组成,就像变换器一样,除了另一个初始大小。内置功能的徒手画也不在乎。
当这些元素被单独 select 编辑时,它们仍然是 "in position"。我没有覆盖任何 selection 方法。
值得一提的是,白板位于应用程序内的一个小部件中,这意味着您可以在显示屏周围拖动白板,因此值 adjustedX
和 adjustedY
。但是,物体总是变换到原点,其他物体正常工作,所以我倾向于排除。
单select离子
组select离子:所有对象selected
组select离子:仅矩形selected
这是创建我的 canvas 和两个形状
的代码
const component = this;
this.canvas = new fabric.Canvas('myCanvas', {
selectionColor: 'rgba(0, 0, 255, 0.1)',
selectionLineWidth: 2,
selection: false,
preserveObjectStacking: true,
});
this.canvas.isDrawingMode = true;
this.canvas.freeDrawingBrush.width = 5;
this.canvas.setHeight(window.innerHeight);
this.canvas.setWidth(window.innerWidth);
$(window).on('resize', function(){
component.canvas.setHeight(window.innerHeight);
component.canvas.setWidth(window.innerWidth);
});
this.setObjectsSelectable(false);
if(this.canvas){
// omitted variable declarations
$(".upper-canvas")
.on('mousedown touchstart',function(e){
isDown = true;
// ...
switch(component.drawingMode){
case DrawingMode.UML:
var rectTop = new fabric.Rect({
width: 1,
height: 1,
left: anchorX,
top: anchorY,
stroke: component.color,
strokeWidth: component.stroke,
fill: '',
selectable: false
});
var rectBottom = new fabric.Rect({
width: 1,
height: 1,
left: anchorX,
top: anchorY,
stroke: component.color,
strokeWidth: component.stroke,
fill: '',
selectable: false
});
component.canvas.add(rectTop);
component.canvas.add(rectBottom);
umlObjectTop = rectTop;
umlObjectBottom = rectBottom;
break;
case DrawingMode.SHAPE:
var rect = new fabric.Rect({
width: 5,
height: 5,
left: anchorX,
top: anchorY,
stroke: component.color,
strokeWidth: component.stroke,
fill: component.fill,
selectable: false
});
component.canvas.add(rect);
drawingObject = rect;
break;
case DrawingMode.CIRCLE:
// ...
break;
}
})
.on('mousemove touchmove', function(e){
// ...
switch(component.drawingMode){
case DrawingMode.UML:
if(!isDown) return;
// ...
if(heightTop > 100){
heightTop = 100;
heightBottom = component.abs(anchorY - adjustedY) - 160;
}
if(anchorX > adjustedX){
umlObjectTop.set({ left: component.abs(adjustedX) });
umlObjectBottom.set({ left: component.abs(adjustedX) });
}
if(anchorY > adjustedY){
umlObjectTop.set({ top: component.abs(adjustedY) });
umlObjectBottom.set({ top: component.abs(adjustedY)+heightTop });
}
umlObjectTop.set({ width: widthT });
umlObjectTop.set({ height: heightTop });
umlObjectBottom.set({ width: widthT });
umlObjectBottom.set({ height: heightBottom });
component.canvas.renderAll();
break;
case DrawingMode.SHAPE:
if(!isDown) return;
if(anchorX > adjustedX){
drawingObject.set({ left: component.abs(adjustedX) });
}
if(anchorY > adjustedY){
drawingObject.set({ top: component.abs(adjustedY) });
}
drawingObject.set({ width: component.abs(anchorX - adjustedX) });
drawingObject.set({ height: component.abs(anchorY - adjustedY) });
component.canvas.renderAll();
break;
case DrawingMode.CIRCLE:
// ...
break;
}
})
.on('mouseup touchend', function(e){
isDown = false;
switch(component.drawingMode){
case DrawingMode.SHAPE:
case DrawingMode.CIRCLE:
component.canvas.add(drawingObject);
break;
}
});
}
注意:selection = false
在应用程序中更改为"selection mode"时激活。
所以我无法真正找到这种行为的原因,但找到了 work-around。
删除对象时,我只是克隆这个元素,删除原始元素并删除克隆的元素,结果对象不再变形。
dropObject(drawingObject: any, id: number, awtype: string) {
const component = this;
drawingObject.clone(function (clone) {
clone.set('selectable', false);
component.addLongClickListener(clone);
clone.toObject = (function (toObject) {
return function () {
return fabric.util.object.extend(toObject.call(this), {
id: this.id,
awtype: this.awtype
});
};
})(clone.toObject);
clone.id = id;
clone.awtype = awtype;
component.canvas.add(clone);
component.canvas.renderAll();
});
this.canvas.remove(drawingObject);
}
在一个 angular 应用程序中,我用 Fabric.js 实现了一个简单的白板,它可以让用户绘制一些基本形状和手绘图。形状是空白和填充的圆形和矩形,以及一个基本的 UML 图模板,它们是两个彼此重叠的单个矩形。
当我select一个或多个对象时,所有矩形和圆实例的位置自动转换到canvas'原点,只留下select离子标记在原来的位置。奇怪的是,这不会发生在 UML 模板中,它最终也由两个简单的矩形组成,就像变换器一样,除了另一个初始大小。内置功能的徒手画也不在乎。
当这些元素被单独 select 编辑时,它们仍然是 "in position"。我没有覆盖任何 selection 方法。
值得一提的是,白板位于应用程序内的一个小部件中,这意味着您可以在显示屏周围拖动白板,因此值 adjustedX
和 adjustedY
。但是,物体总是变换到原点,其他物体正常工作,所以我倾向于排除。
单select离子
组select离子:所有对象selected
组select离子:仅矩形selected
这是创建我的 canvas 和两个形状
的代码 const component = this;
this.canvas = new fabric.Canvas('myCanvas', {
selectionColor: 'rgba(0, 0, 255, 0.1)',
selectionLineWidth: 2,
selection: false,
preserveObjectStacking: true,
});
this.canvas.isDrawingMode = true;
this.canvas.freeDrawingBrush.width = 5;
this.canvas.setHeight(window.innerHeight);
this.canvas.setWidth(window.innerWidth);
$(window).on('resize', function(){
component.canvas.setHeight(window.innerHeight);
component.canvas.setWidth(window.innerWidth);
});
this.setObjectsSelectable(false);
if(this.canvas){
// omitted variable declarations
$(".upper-canvas")
.on('mousedown touchstart',function(e){
isDown = true;
// ...
switch(component.drawingMode){
case DrawingMode.UML:
var rectTop = new fabric.Rect({
width: 1,
height: 1,
left: anchorX,
top: anchorY,
stroke: component.color,
strokeWidth: component.stroke,
fill: '',
selectable: false
});
var rectBottom = new fabric.Rect({
width: 1,
height: 1,
left: anchorX,
top: anchorY,
stroke: component.color,
strokeWidth: component.stroke,
fill: '',
selectable: false
});
component.canvas.add(rectTop);
component.canvas.add(rectBottom);
umlObjectTop = rectTop;
umlObjectBottom = rectBottom;
break;
case DrawingMode.SHAPE:
var rect = new fabric.Rect({
width: 5,
height: 5,
left: anchorX,
top: anchorY,
stroke: component.color,
strokeWidth: component.stroke,
fill: component.fill,
selectable: false
});
component.canvas.add(rect);
drawingObject = rect;
break;
case DrawingMode.CIRCLE:
// ...
break;
}
})
.on('mousemove touchmove', function(e){
// ...
switch(component.drawingMode){
case DrawingMode.UML:
if(!isDown) return;
// ...
if(heightTop > 100){
heightTop = 100;
heightBottom = component.abs(anchorY - adjustedY) - 160;
}
if(anchorX > adjustedX){
umlObjectTop.set({ left: component.abs(adjustedX) });
umlObjectBottom.set({ left: component.abs(adjustedX) });
}
if(anchorY > adjustedY){
umlObjectTop.set({ top: component.abs(adjustedY) });
umlObjectBottom.set({ top: component.abs(adjustedY)+heightTop });
}
umlObjectTop.set({ width: widthT });
umlObjectTop.set({ height: heightTop });
umlObjectBottom.set({ width: widthT });
umlObjectBottom.set({ height: heightBottom });
component.canvas.renderAll();
break;
case DrawingMode.SHAPE:
if(!isDown) return;
if(anchorX > adjustedX){
drawingObject.set({ left: component.abs(adjustedX) });
}
if(anchorY > adjustedY){
drawingObject.set({ top: component.abs(adjustedY) });
}
drawingObject.set({ width: component.abs(anchorX - adjustedX) });
drawingObject.set({ height: component.abs(anchorY - adjustedY) });
component.canvas.renderAll();
break;
case DrawingMode.CIRCLE:
// ...
break;
}
})
.on('mouseup touchend', function(e){
isDown = false;
switch(component.drawingMode){
case DrawingMode.SHAPE:
case DrawingMode.CIRCLE:
component.canvas.add(drawingObject);
break;
}
});
}
注意:selection = false
在应用程序中更改为"selection mode"时激活。
所以我无法真正找到这种行为的原因,但找到了 work-around。
删除对象时,我只是克隆这个元素,删除原始元素并删除克隆的元素,结果对象不再变形。
dropObject(drawingObject: any, id: number, awtype: string) {
const component = this;
drawingObject.clone(function (clone) {
clone.set('selectable', false);
component.addLongClickListener(clone);
clone.toObject = (function (toObject) {
return function () {
return fabric.util.object.extend(toObject.call(this), {
id: this.id,
awtype: this.awtype
});
};
})(clone.toObject);
clone.id = id;
clone.awtype = awtype;
component.canvas.add(clone);
component.canvas.renderAll();
});
this.canvas.remove(drawingObject);
}