FabricJs-SVG对象剪切区域 [英] FabricJs - Clipping area by SVG object

查看:123
本文介绍了FabricJs-SVG对象剪切区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对FabricJS对象有问题.我想创建一个剪切区域(svg对象),该区域将剪切加载的图像.

I have a problem with FabricJS objects. I would like to create a clipping area (svg object), which will clips loaded images.

我在加载的图像上使用clipTo方法,将其传递到剪切区域形状对象(SVG)中,但是它不起作用,因为从FabricJS的意义上讲,SVG不是形状对象.有什么方法可以将加载的SVG转换为Polygon或Rect之类的FabricJS形状?

I'm using clipTo method on loaded image passing it into clipping area shape object (SVG), but it does not work, because the SVG is not shape object in sense of FabricJS. Is there any way to convert the loaded SVG into FabricJS shape like Polygon or Rect?

如果我使用的话,它几乎可以很好地工作:

It almost works good if I will use:

globalCompositeOperation = 'source-atop' 

在加载的图像上(并删除clipTo功能),但是如果我将移动/调整大小/旋转图像,则它将与主剪切区域(最大矩形)的边界重叠.图像不应与灰色矩形以外的其他对象进行交互,尤其是在主剪切区域中. 也许有一种方法可以通过与globalCompositeOperation一起使用来实现这一目标?

on the loaded image (and remove clipTo function), but if I will move/resize/rotate the image it overlaps border of the main clipping area (the biggest rect). Image should not interact with other objects outside the grey rect, especially with main clipping area. Maybe is there a way to achieve this by playing with globalCompositeOperation?

我将非常感谢您提供任何提示.

I will be very grateful for any tips.

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

Here is JSFiddle of my problem: https://jsfiddle.net/6nfdr1ng/

,这里是几乎可用的版本(带有源代码顶部): https://jsfiddle.net/ud9nev1g/

and here almost working version (with 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>

推荐答案

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

I resolved my problem by combining the SVG shape into one path (without any polygons any other svg objects), then I pass the svg coords into fabircJS path. The valid SVG coords looks like that "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,
            });
     }

我希望它会对其他人有所帮助:)

I hope it will help someone else :)

这篇关于FabricJs-SVG对象剪切区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆