在 node.js 中使用 fabric.js 渲染和操作服务器端画布

Posted

技术标签:

【中文标题】在 node.js 中使用 fabric.js 渲染和操作服务器端画布【英文标题】:Using fabric.js to render and manipulate server-side canvas in node.js 【发布时间】:2012-12-01 07:34:52 【问题描述】:

我正在尝试将fabric.js(v0.9.21,在ubuntu 12.04上通过npm安装)与node.js一起在服务器上呈现画布(以后可以在没有客户端交互的情况下对其进行操作和扩展)。为了进行实验,我在客户端创建了一个简单的画布,然后使用canvas.toJSON() 方法将其导出为 JSON。当我尝试仅使用该 JSON 重新加载画布时,效果很好(使用 canvas.loadFromJSON())。

你可以看到整个例子in this fiddle。

(如果它不起作用,则图像可能已过期 - 替换链接)。

然后我尝试使用这个简单的脚本在服务器端做同样的事情:

var fabric = require('fabric').fabric;
var fs     = require('fs');
var canvas = fabric.createCanvasForNode(570, 600);

fs.readFile('kitty.json', 'utf8', function(err, data) 
  canvas.loadFromJSON(data);
);

当我运行这个脚本(使用node script.jsrequire('./script.js') from inside node)时,我遇到了奇怪的崩溃:

> http.createClient is deprecated. Use `http.request` instead.

/usr/lib/node_modules/fabric/dist/all.js:12429
      ctx.drawImage(
          ^
Error: Image given has not completed loading
    at klass.fabric.Image.fabric.util.createClass._render (/usr/lib/node_modules/fabric/dist/all.js:12429:11)
    at klass.fabric.Image.fabric.util.createClass.render (/usr/lib/node_modules/fabric/dist/all.js:12303:12)
    at klass.(anonymous function) [as render] (/usr/lib/node_modules/fabric/dist/all.js:2405:48)
    at extend._draw (/usr/lib/node_modules/fabric/dist/all.js:5332:16)
    at extend.renderAll (/usr/lib/node_modules/fabric/dist/all.js:5468:16)
    at extend.insertAt (/usr/lib/node_modules/fabric/dist/all.js:5381:37)
    at fabric.util.object.extend._enlivenObjects (/usr/lib/node_modules/fabric/dist/all.js:7694:15)
    at Array.forEach (native)
    at fabric.util.object.extend._enlivenObjects (/usr/lib/node_modules/fabric/dist/all.js:7693:24)
    at onLoaded (/usr/lib/node_modules/fabric/dist/all.js:1995:11)

画布中有一张图片(由 interwebs 的小猫收藏提供)和一个文本项。

我对 node 还很陌生,所以也许我在此过程中遗漏了一些东西 - 任何提示都会很棒。谢谢。

【问题讨论】:

你有哪些版本的节点和节点画布?您是否也遵循了 node-canvas 安装说明? github.com/LearnBoost/node-canvas/wiki/Installation---Ubuntu 我在 Ubuntu 12.04 上使用画布 0.13.1、节点 0.8.16 和结构 0.9.21。我按照说明再次重新安装以确保结果仍然相同。您能否使用您的设置运行我的代码(假设版本相同)?谢谢! 嗯,这很奇怪......缩小到http.request 现在有不同的签名(显然在节点 0.8.x 中)。我以为我们在生产中使用 0.8,这让我想知道事情如何仍然有效。无论如何,用这个替换 request 方法似乎可以做到 - gist.github.com/600934872f28397e6350。我将对此进行更多研究并更新 Fabric 本身。 很高兴知道 - 感谢您的调查。 【参考方案1】:

我认为问题在于您试图在将图像添加到画布之前渲染画布。在我的情况下,在 loadFromJSON() 的回调中调用 renderAll() 解决了这个问题。

canvas.loadFromJSON(JSON.stringify(json),canvas.renderAll.bind(canvas));

canvas.loadFromJSON(JSON.stringify(json),canvas.renderAll());

这将确保仅在将 json 数据加载到画布后才呈现画布

var canvas = new fabric.Canvas('mycanvas');
var json = 
  "objects": [
    "type": "image",
    "left": 300,
    "top": 295,
    "width": 500,
    "height": 375,
    "fill": "rgb(0,0,0)",
    "overlayFill": null,
    "stroke": null,
    "strokeWidth": 1,
    "strokeDashArray": null,
    "scaleX": 1,
    "scaleY": 1,
    "angle": 0,
    "flipX": false,
    "flipY": false,
    "opacity": 1,
    "selectable": true,
    "hasControls": true,
    "hasBorders": true,
    "hasRotatingPoint": false,
    "transparentCorners": true,
    "perPixelTargetFind": false,
    "src": "http://t3.gstatic.com/images?q=tbn:ANd9GcTE0NOJqQ46En2x1T61cZf_S4RwxOTtxcLsmfQUHkSXk5SOx-zaYnPj6jYI",
    "filters": []
  , 
    "type": "text",
    "left": 300,
    "top": 537,
    "width": 116,
    "height": 57.6,
    "fill": "rgb(0,0,0)",
    "overlayFill": null,
    "stroke": null,
    "strokeWidth": 1,
    "strokeDashArray": null,
    "scaleX": 1,
    "scaleY": 1,
    "angle": 0,
    "flipX": false,
    "flipY": false,
    "opacity": 1,
    "selectable": true,
    "hasControls": false,
    "hasBorders": true,
    "hasRotatingPoint": false,
    "transparentCorners": true,
    "perPixelTargetFind": false,
    "text": "Kitten!",
    "fontSize": 12,
    "fontWeight": 400,
    "fontFamily": "Lato",
    "fontStyle": "",
    "lineHeight": 1.2,
    "textDecoration": "",
    "textShadow": "",
    "textAlign": "center",
    "path": null,
    "strokeStyle": "",
    "backgroundColor": "",
    "textBackgroundColor": "",
    "useNative": true
  ],
  "background": "rgba(0, 0, 0, 0)"
;
canvas.loadFromJSON(JSON.stringify(json), canvas.renderAll.bind(canvas));
#mycanvas 
  border: 1px solid black;
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.1.0/fabric.all.min.js"></script>
<canvas id="mycanvas"  ></canvas>

【讨论】:

以上是关于在 node.js 中使用 fabric.js 渲染和操作服务器端画布的主要内容,如果未能解决你的问题,请参考以下文章

Fabric.JS 与 Node.JS - 导出为 PNG/JPEG

在 python 服务器上从 Fabric.js JSON 构造图像

在fabric.js中使用stateProperties和hasStateChanged实现撤消/重做

如何使用 Fabric.js 将图像上传到画布?

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

Fabric.js 橡皮擦问题画布