FabricJs - 按SVG对象剪切区域

时间:2018-02-08 17:12:37

标签: javascript svg fabricjs

我遇到FabricJS对象的问题。我想创建一个剪辑区域(svg对象),它将剪切加载的图像。

我在加载的图像上使用clipTo方法将其传递到剪切区域形状对象(SVG),但它不起作用,因为SVG不是FabricJS意义上的形状对象。有没有办法将加载的SVG转换为FabricJS形状,如Polygon或Rect?

如果我将使用它几乎可行:

globalCompositeOperation = 'source-atop' 

在加载的图像上(并删除clipTo函数),但是如果我将移动/调整大小/旋转图像,它会与主剪切区域(最大矩形)的边界重叠。图像不应与灰色矩形之外的其他对象交互,尤其是对于主剪切区域。 也许通过使用globalCompositeOperation可以实现这一目标吗?

我将非常感谢任何提示。

这是我的问题的JSFiddle: https://jsfiddle.net/6nfdr1ng/

这里几乎正常工作的版本(带有source-atop): https://jsfiddle.net/ud9nev1g/

<input type="file" id="image"><br>
<canvas id="canvas" width="530" height="600"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.21/fabric.min.js"></script>
<script type="text/javascript">
    var canvas = new fabric.Canvas('canvas', {
        'selection': false
    });

    /**
     * loading man clipping rect
     */
    var clippingRect = new fabric.Rect({
        width: 185,
        height: 400,
        fill: 'transparent',
        stroke: 1,
        opacity: 1,
        hasBorders: false,
        hasControls: false,
        hasRotatingPoint: false,
        selectable: false,
        preserveObjectStacking: true,
        objectCaching: false
    });
    canvas.add(clippingRect);
    canvas.renderAll();

    /**
     * loading shape which should be another clipping area for loaded image
     */
    var svgString = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 63.7 63.7"><defs><style>.cls-1{fill:#79797a;fill-rule:evenodd;}</style></defs><title>Asset 4</title><g id="Layer_2" data-name="Layer 2"><g id="kwadrat"><path class="cls-1" d="M0,0H63.7V63.7H0Z"/></g></g></svg>';
    var retinaScalling = canvas.getRetinaScaling();
    fabric.loadSVGFromString(svgString, function (objects, options) {
        var shapeObject = fabric.util.groupSVGElements(objects, options);
        shapeObject.scaleX = 0.5;
        shapeObject.scaleY = 0.5;
        shapeObject.set('id', 'shape');
        shapeObject.scaleToWidth(clippingRect.getWidth());
        shapeObject.setCoords();
        shapeObject.clipTo = function (ctx) {
            ctx.save();
            ctx.setTransform(retinaScalling, 0, 0, retinaScalling, 0, 0);
            clippingRect.render(ctx);
            ctx.restore();
        };
        shapeObject.center();
        shapeObject.setCoords();
        canvas.setActiveObject(shapeObject);
        canvas.add(shapeObject);
        canvas.renderAll();
    });

    /**
     * loading image
     */
    document.getElementById('image').onchange = function (e) {
        var reader = new FileReader();
        var clippingAreaShape = canvas.getActiveObject();
        reader.onload = function (event) {
            var img = new Image();
            img.onload = function () {
                var shapeImageObject = new fabric.Image(img, {
                    objectCaching: false,
                    hasControls: true,
                    selectable: true
                });
                shapeImageObject.scaleToHeight(clippingAreaShape.getWidth());
                shapeImageObject.set('id', 'shape-image');
                shapeImageObject.set({
                    left: clippingAreaShape.left,
                    top: clippingAreaShape.top
                });
                shapeImageObject.clipTo = function (ctx) {
                    ctx.save();
                    ctx.setTransform(retinaScalling, 0, 0, retinaScalling, 0, 0);
                    clippingAreaShape.render(ctx);
                    ctx.restore();
                };
                // shapeImageObject.globalCompositeOperation = 'source-atop';
                canvas.add(shapeImageObject);
                canvas.renderAll();
                canvas.setActiveObject(shapeImageObject);
                shapeImageObject.setCoords();
            };
            img.src = event.target.result;
        };
        reader.readAsDataURL(e.target.files[0]);
    }

</script>

1 个答案:

答案 0 :(得分:1)

我通过将SVG形状组合成一条路径(没有任何其他svg对象的任何多边形)解决了我的问题,然后我将svg coords传递给fabircJS路径。有效的SVG坐标看起来像“M0,0H63.7V63.7H0Z”

fabric.loadSVGFromURL('object.svg', function (objects, options) {
            let img1 = new fabric.Path(objects[0].d, {
                fill: '#333',
                opacity: 1,
                hasBorders: true,
                hasControls: true,
                hasRotatingPoint: true,
                selectable: true,
                preserveObjectStacking: true,
                objectCaching: false,
            });
     }

我希望它会帮助别人:)