如何在fabric js中覆盖canvas.add()方法

Posted

技术标签:

【中文标题】如何在fabric js中覆盖canvas.add()方法【英文标题】:how to override canvas.add() method in fabric js 【发布时间】:2020-01-17 07:44:42 【问题描述】:

我正在使用一个图像编辑器,我想在其中将图像添加到带有动画的画布中。 我尝试覆盖 canvas.add() 方法但无法播放动画。

我使用的是 Fabric js 版本 1.7.22。 当我尝试谷歌搜索时。我找到了一种使用动画添加对象的解决方案,但在那个演示中,他们使用自定义新方法“fxadd()”来添加对象。

这里是参考链接: https://github.com/fabricjs/fabric.js/issues/77

但是我的代码太长了,根本不想替换函数名。 有什么方法可以覆盖现有的面料 canvas.add() 方法然后请帮助我。

fabric.Canvas.prototype.add = (function(object, callback) 
  return function() 
    console.log('add into canvas', this);
    this.add(object); // here call self method which result in infinit loop
    object.animate('top', '100', 
      onChange: this.renderAll.bind(this),
      duration: 1000,
      easing: fabric.util.ease.easeOutElastic,
      onComplete: function() 
    );
  ;
)(fabric.Canvas.prototype.add);

var canvas = new fabric.Canvas('canvas1')
var btn = document.getElementById('animate');

btn.addEventListener('click', function() 
  canvas.clear();
  setTimeout(function() 
    run();
  , 800);
);
var run = function() 
  var rect = new fabric.Rect(
    left: 50,
    top: 10,
    fill: 'red',
    width: 100,
    height: 100,
  );

  canvas.add(rect)

【问题讨论】:

我尝试覆盖 canvas.add() - 你能具体说明你尝试了什么,什么没用吗? 这里是小提琴:jsfiddle.net/Mark_1998/h24u0ncm 请阅读小提琴中的评论。我已经写出了产生这个问题的原因。 【参考方案1】:

看起来您正在尝试使用闭包覆盖原型方法,这通常是一种聪明的方法,只是它在您的 sn-p 中没有完全正确地完成。考虑一下您使用的构造的简化版本:

fabric.Canvas.prototype.add = (function A(argA) 
  return function B(argsB)
    //..
  
)(fabric.Canvas.prototype.add)

在这里您调用function A,将fabric.Canvas.prototype.add 作为参数传递。这将创建一个闭包,将原始的 fabric.Canvas.prototype.add 保留在 function A 的范围内。然后,您将分配任何function A 返回给fabric.Canvas.prototype.add。实际上,这转化为

fabric.Canvas.prototype.add = function B(argsB) /*... */

现在只有function B 可以访问原来的fabric.Canvas.prototype.add

回到你的 sn-p,注意你是如何期望 object, callback 作为 function A 的参数而在 function B 中没有参数 - 这没有任何用处(见上文)。此外,当您拨打this.add() 时 - 这是您应该拨打原始 add() 而不是 的地方。否则,您将获得无限递归。


话虽如此,以下是正确的做法:

fabric.Canvas.prototype.add = (function(originalFn) 
  return function(...args) 
    originalFn.call(this, ...args)
    args[0].animate('top', '100', 
        onChange: this.renderAll.bind(this),
        duration: 1000,
        easing: fabric.util.ease.easeOutElastic,
        onComplete: function () 
        
    );
    return this
  ;
)(fabric.Canvas.prototype.add);

注意其余参数...args 的用法,因为add() 应该将多个对象作为参数处理。我在第一个传递的对象上调用 animate(),所以你可能想要更改它。

另外,不要忘记原始的 add() 应该返回 fabric.Canvas 的实例以使链接工作,因此最后是 return this

【讨论】:

非常感谢您的帮助。它对我有用

以上是关于如何在fabric js中覆盖canvas.add()方法的主要内容,如果未能解决你的问题,请参考以下文章

使用 fabric.js 在画布中加载 JSON

如何使用 fabric.js 在画布上画一条线

是否可以在 fabric.js 中为路径设置动画?

文本框导致fabric js中的字体问题

在 Fabric.js 中将对象添加到画布时设置对象的位置

Fabric.js 图像点击和动画外部添加功能