本文介绍了在Fabric.js中处理可加载蒙版的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当尝试遮罩对象时,我有这个赏金打开 Fabricjs遮罩具有转换的对象Fabric.js.

I have this bounty open Fabricjs mask object with transformation when trying to mask objects with Fabric.js.

我正在开发的工具应允许用户在图像对象上绘制蒙版,并在蒙版之前或之后对该对象应用转换(倾斜比例旋转等).我即将获得此结果,但是有角度的对象仍无法正常工作.

The tool I'm developing should allow users to draw a mask over image objects, and apply transformations (skew scale rotate etc) to this object before or after the mask. I'm close to obtaining this result but objects with an angle are still not working.

我也在尝试使用toJSONloadFromJSON将该对象保存到数据库中,但是在尝试完成几天后,我意识到该解决方案将不起作用,因为ctx范围之外的任何引用从JSON加载时无法访问,因此它们会引发错误.

I'm also trying to save this object to a database using toJSON and loadFromJSON, but after a few days trying to accomplish this I realize that this solution will not work because any references outside the ctx scope can't be accessed while loading from JSON, so they throw an error.

    clipTo: function(ctx) {
        mask.set({
            left:
                -object.width / 2 -
                (mask.width / 2) * originalMaskScaleX -
                originalObjLeft / originalObjScaleX,
            top:
                -object.height / 2 -
                (mask.height / 2) * originalMaskScaleY -
                originalObjTop / originalObjScaleY,
            objectCaching: false
        });
        mask.render(ctx);
    }

Fabric.js是此问题的正确解决方案吗?我应该使用其他东西吗?如果可以使用Fabric.js完成此操作,什么是正确的方法?

Is Fabric.js the proper solution to this problem? Should I be using something else? If this can be done with Fabric.js, what is the proper approach?

推荐答案

我扩展了fabric.Image并添加了一些自定义属性.我也将面罩贴在fabric.Image上.对于fabric.Image.fromObject,在加载图像后,我还需要它也加载mask(我知道是路径)并附加到图像.这是一个快速的实现.我很确定这段代码可以简化.请告诉我是否有不清楚的信息

I extended fabric.Image with some custom attributes.Also I attached the mask on fabric.Image.For fabric.Image.fromObject after the image is loaded I need it to load also the mask( which I know is a path) and attach to image.This is a fast implementation. I'm pretty sure this code can be simplified.Please tell me know if something is not clear enougth

 

    canvas = new fabric.Canvas("canvas", {
   backgroundColor: "lightgray",
   width: 1280,
   height: 720,
   preserveObjectStacking: true,
   selection: false,
   stateful: true
 });

 canvas.isDrawingMode = true;
 canvas.freeDrawingBrush.color = "black";
 canvas.freeDrawingBrush.width = 2;

 canvas.on("path:created", function(options) {

   clip(options.path);
 });

 function clip(path) {
   canvas.isDrawingMode = false;
   canvas.remove(path);

   let mask = new fabric.Path(path.path, {
     top: object.top,
     left: object.left,
     objectCaching: false,
     strokeWidth: 0,
     scaleX: 1 / object.scaleX,
     scaleY: 1 / object.scaleY,
     pathOffset: {
       x: 0,
       y: 0
     }
   });
   object = canvas.getObjects()[0];
   object.originalObjLeft = object.left,
     object.originalObjTop = object.top,
     object.originalMaskScaleX = mask.scaleX,
     object.originalMaskScaleY = mask.scaleY,
     object.originalObjScaleX = object.scaleX,
     object.originalObjScaleY = object.scaleY;
     var transformedTranslate = object.translateToGivenOrigin({
        x: object.left,
        y: object.top
    }, object.originX, object.originY, 'center', 'center');
    object.originalTransformLeft = transformedTranslate.x - object.getCenterPoint().x;
    object.originalTransformTop = transformedTranslate.y - object.getCenterPoint().y;
    object.originalAngle = object.angle;
    
    
   object.clipMask = mask;
   object.set({
     clipTo: function(ctx) {
			 
        ctx.save();
        ctx.rotate(-this.originalAngle * Math.PI / 180);

        ctx.translate(this.originalTransformLeft / this.originalObjScaleX, this.originalTransformTop / this.originalObjScaleY)

       
       
       this.clipMask.set({
         left: -object.width / 2 - (this.clipMask.width / 2 * this.originalMaskScaleX) - this.originalObjLeft / this.originalObjScaleX,
         top: -object.height / 2 - (this.clipMask.height / 2 * this.originalMaskScaleY) - this.originalObjTop / this.originalObjScaleY,
         objectCaching: false
       });
       this.clipMask.render(ctx);
        ctx.restore();
     }
   });

   canvas.requestRenderAll();
 }

 // image

 let image = new Image();


 image.onload = function() {
   object = new fabric.Image(image, {
     width: 500,
     height: 500,
     scaleX: 0.8,
     scaleY: 0.8,
      angle: 45,
     top: 50,
     left: 100
   });

   canvas.add(object);
 };

 image.src = "http://i.imgur.com/8rmMZI3.jpg";

 fabric.util.object.extend(fabric.Image.prototype, {
   clipMask: null,
   originalObjLeft: 0,
   originalObjTop: 0,
   originalMaskScaleX: 1,
   originalMaskScaleY: 1,
   originalObjScaleX: 1,
   originalObjScaleY: 1,
   originalAngle:0,
   originalTransformLeft:0,
   originalTransformTop:0
 });
 fabric.Image.prototype.toObject = (function(toObject) {
   return function(propertiesToInclude) {
     return fabric.util.object.extend(toObject.call(this, propertiesToInclude), {
       clipMask: this.clipMask ? this.clipMask.toObject(propertiesToInclude) : null,
       originalObjLeft: this.originalObjLeft,
       originalObjTop: this.originalObjTop,
       originalMaskScaleX: this.originalMaskScaleX,
       originalMaskScaleY: this.originalMaskScaleY,
       originalObjScaleX: this.originalObjScaleX,
       originalObjScaleY: this.originalObjScaleY,
       originalAngle:this.originalAngle,
       originalTransformLeft:this.originalTransformLeft,
       originalTransformTop:this.originalTransformTop
     });
   }
 })(fabric.Image.prototype.toObject);

 fabric.Image.fromObject = (function(fromObject) {
   return function(_object, callback) {
     fromObject.call(this, _object, (function(callback, _object) {
       return function(image) {
         if (image.clipMask) {
           fabric.Path.fromObject(image.clipMask, (function(callback) {
             return function(path) {
               path.pathOffset.x = 0;
               path.pathOffset.y = 0;
               image.clipMask = path;
               callback(image);
             }
           })(callback))
         } else {
           callback(image);
         }
       }
     })(callback, _object));
     return;
   }
 })(fabric.Image.fromObject)




 $("#button1").on('click', function() {
   let dataJSON = canvas.toJSON();
   canvas.clear();
   canvas.loadFromJSON(
     dataJSON,
     canvas.renderAll.bind(canvas));
 })
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.6/fabric.js"></script>
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<button id="button1">SAve/Load JSON</button>
<div class="canvas__wrapper">
  <canvas id="canvas" width="1280" height="720"></canvas>
</div>

更新我更新了代码,从此处:

UPDATEI updated the code to fix the problem with angle from here:

这篇关于在Fabric.js中处理可加载蒙版的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-14 16:21