旋转fabric.js时的组控制偏移

Posted

技术标签:

【中文标题】旋转fabric.js时的组控制偏移【英文标题】:Group controls offset when rotated fabric.js 【发布时间】:2019-05-20 10:09:56 【问题描述】:

我创建了一个结构自定义类“VectorPlaceholder”,它基本上是一个包含 Rectangle 和 Vector 的组:

// Fabric.js custom vector EPS object
fabric.VectorPlaceholder = fabric.util.createClass(fabric.Group, 
    async: true,
    type: 'vector-placeholder',
    lockUniScalingWithSkew: false,
    noScaleCache: true,


    initialize: function (options)                 

        boundsRectangle = new fabric.Rect(            
            strokeDashArray: [10,10],
            originX: 'center',
            originY: 'center',
            stroke: '#000000',
            strokeWidth: 1,
            width: options.width || 300,
            height: options.height || 300,
            fill: 'rgba(0, 0, 0, 0)',            
        );

        this.setControlsVisibility(            
            ml: false,
            mb: false,
            mr: false,
            mt: false,            
        );

        this.originX = 'center',
        this.originY = 'center',

        this.callSuper('initialize', [boundsRectangle], options);

    ,

    setVector: function (vector)         
        //We remove any EPS that was in that position
        var EPSGroup = this;
        EPSGroup.forEachObject(function (object) 
            if (object && object.type != "rect") 
                EPSGroup.remove(object);
            
        );

        var scale = 1;        
        var xOffset = EPSGroup.getScaledWidth() / 2;
        var yOffset = EPSGroup.getScaledHeight() / 2;
        if (vector.height > vector.width)             
            scale = EPSGroup.getScaledHeight() / vector.height;
            xOffset = xOffset - (EPSGroup.getScaledWidth() - vector.width * scale) / 2

        
        else 
            scale = EPSGroup.getScaledWidth() / vector.width;
            yOffset = yOffset - (EPSGroup.getScaledHeight() - vector.height * scale) / 2

        

        vector.left = EPSGroup.left - xOffset;
        vector.top = EPSGroup.top - yOffset;        
        vector.set('scaleY', scale);
        vector.set('scaleX', scale);
        var angle = 0;        
        if (EPSGroup.get('angle')) 
            angle = EPSGroup.get('angle');
            vector.setAngle(angle);                        
                
        EPSGroup.addWithUpdate(vector);
        EPSGroup.setCoords();      
    ,

);

这个类的想法是有一个占位符,用户可以在其中上传 SVG。 这是通过调用 fabric.loadSVGFromString 然后将结果传递给我的自定义类(setVector)中的函数来完成的

fabric.loadSVGFromString(svgString, function(objects, options) 
   // Group the SVG objects to make a single element
   var a = fabric.util.groupSVGElements(objects, options);
   var EPSGroup = new fabric.VectorPlaceholder();
   EPSGroup.setVector(a);   

当我创建自定义对象并且不旋转它时,这非常有效。如您所见,组控件与虚线矩形对齐。

问题是当我创建一个空的 VectorPlaceholder 并手动旋转它时。手动旋转后,调用 setVector 时会发生以下情况:

我不明白为什么组控制忽略轮换,我做错了什么?如何使组控件呈现与旋转的矩形对齐?

【问题讨论】:

【参考方案1】:

制作setVector方法后需要设置角度 http://jsfiddle.net/2segrwx0/1/

// Fabric.js custom vector EPS object
fabric.VectorPlaceholder = fabric.util.createClass(fabric.Group, 
    async: true,
    type: 'vector-placeholder',
    lockUniScalingWithSkew: false,
    noScaleCache: true,


    initialize: function (options)                 

        boundsRectangle = new fabric.Rect(            
            strokeDashArray: [10,10],
            originX: 'center',
            originY: 'center',
            stroke: '#000000',
            strokeWidth: 1,
            width: options.width || 300,
            height: options.height || 300,
            fill: 'rgba(0, 0, 0, 0)',            
        );

        this.setControlsVisibility(            
            ml: false,
            mb: false,
            mr: false,
            mt: false,            
        );

        this.originX = 'center',
        this.originY = 'center',

        this.callSuper('initialize', [boundsRectangle], options);

    ,

    setVector: function (vector)         
        //We remove any EPS that was in that position
        var EPSGroup = this;
        EPSGroup.forEachObject(function (object) 
            if (object && object.type != "rect") 
                EPSGroup.remove(object);
            
        );

        var scale = 1;        
        var xOffset = EPSGroup.getScaledWidth() / 2;
        var yOffset = EPSGroup.getScaledHeight() / 2;
        if (vector.height > vector.width)             
            scale = EPSGroup.getScaledHeight() / vector.height;
            xOffset = xOffset - (EPSGroup.getScaledWidth() - vector.width * scale) / 2

        
        else 
            scale = EPSGroup.getScaledWidth() / vector.width;
            yOffset = yOffset - (EPSGroup.getScaledHeight() - vector.height * scale) / 2

        

        vector.left = EPSGroup.left - xOffset;
        vector.top = EPSGroup.top - yOffset;        
        vector.set('scaleY', scale);
        vector.set('scaleX', scale);
        /*var angle = 0;        
        if (EPSGroup.get('angle')) 
            angle = EPSGroup.get('angle');
            vector.setAngle(angle);                        
               */ 
        EPSGroup.addWithUpdate(vector);
        EPSGroup.setCoords();      
    ,

);

 canvas = new fabric.Canvas('c', 
 
);


fabric.loadSVGFromString('<svg  ><polygon points="100,10 40,198 190,78 10,78 160,198" style="fill:lime;stroke:purple;stroke-width:5;fill-rule:nonzero;" /></svg>', function(objects, options) 
   // Group the SVG objects to make a single element
   var a = fabric.util.groupSVGElements(objects, options);
   var EPSGroup = new fabric.VectorPlaceholder();
   EPSGroup.left=200;
   EPSGroup.top=200;

   EPSGroup.setVector(a);  
    EPSGroup.angle=45;
   canvas.add(EPSGroup);
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.5/fabric.js"></script>
<canvas id="c" width=500 height=300 ></canvas>

【讨论】:

以上是关于旋转fabric.js时的组控制偏移的主要内容,如果未能解决你的问题,请参考以下文章

UIScrollview 偏移问题

如何根据旋转偏移边界圆?

图片的偏移和旋转问题

旋转滑块 wordpress 全屏和容器偏移

iOS 带有偏移的垂直旋转木马

在 C++ 中计算相似图像的偏移/倾斜/旋转