javascript - 如何在fabric js中重写canvas.add()方法

标签 javascript animation html5-canvas fabricjs addition

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

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

这是引用链接: https://github.com/fabricjs/fabric.js/issues/77

但是我的代码太长并且不想在所有地方替换函数名称。 有什么方法可以覆盖现有的 Fabric 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)
}

最佳答案

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

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

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

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

直到现在函数B才可以访问原始的fabric.Canvas.prototype.add

返回到您的代码片段,请注意您如何期望对象,回调作为函数A的参数,而函数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这个在最后。

关于javascript - 如何在fabric js中重写canvas.add()方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57957387/

相关文章:

html - 如何使用 Canvas 同时调整图像大小和旋转图像

c# - 如何从嵌入式资源加载 HTML/JavaScript 到 winform web 浏览器

javascript - 在浏览器中提交表单和在javascript中多线程

javascript - 在JS中,我想检查cookie,如果不存在,则运行动画函数并写入cookie,如果存在,则跳过动画。

c# - PictureBox 可以在 Windows 应用程序中显示动画 GIF 吗?

javascript - 有什么方法可以绕过 Canvas 安全异常(外部图像到数据字符串)

JavaScript 为 Adob​​e Form Field 自动计算 24 小时工时?

javascript - xpath 无法识别标签

css - 当元素改变位置时动画元素(响应式布局)

javascript - 我如何在 Canvas 动画上写文字