首页 > 解决方案 > Fabric.js:组选择将某些对象的中心位置转换为画布原点

问题描述

在一个 Angular 应用程序中,我使用 Fabric.js 实现了一个简单的白板,它可以让用户绘制一些基本的形状和手绘。这些形状是空的,填充的圆形和矩形,以及一个基本的 UML 图模板,它们是两个相互重叠的单个矩形。

当我选择一个或多个对象时,所有矩形和圆形实例的位置都会自动转换到画布的原点,只将选择标记留在其原始位置。奇怪的是,UML 模板不会发生这种情况,它最终也由两个简单的矩形组成,就像转换器一样,除了另一个初始大小。内置功能的手绘图也不在意。

当这些元素被单独选择时,它们保持“就位”。我没有覆盖任何选择方法。

值得一提的是,白板位于应用程序内的小部件中,这意味着您可以将白板拖动到显示屏周围,因此值adjustedXadjustedY. 但是,对象总是转换为原点,其他对象正常工作,所以我倾向于排除它。

单选

在此处输入图像描述

组选择:选择所有对象

在此处输入图像描述

组选择:仅选择矩形

在此处输入图像描述

这是创建我的画布和两个形状的代码

        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在应用程序中更改为“选择模式”时会被激活。

标签: angularfabricjsselection

解决方案


所以我并没有真正找到这种行为的原因,但找到了一种解决方法。

删除对象时,我只是克隆此元素,删除原始元素并删除克隆的元素,然后tadaaa,对象不再被转换。

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

推荐阅读