从包含图像引用的 JSON 对象加载图像



我正在构建一个API,该API将从Konva阶段获取JSON对象输出并将其转换为服务器端的图像。我正在使用konva-nodenpm 包,它运行得非常好,直到加载可能是原始"设计"一部分的远程图像。我可以从这个答案中看到我们如何在浏览器中解决问题,但是在 Konva 的 nodejs 实现中,这似乎以不同的方式工作。

示例 JSON 输入如下所示:

let json = {
"attrs": {
"width": 600,
"height": 600
},
"className": "Stage",
"children": [{
"attrs": {},
"className": "Layer",
"children": [{
"attrs": {
"src": "https://ichef.bbci.co.uk/onesport/cps/480/cpsprodpb/1859A/production/_101883799_gettyimages-844211624.jpg"
},
"className": "Image"
}]
}, {
"attrs": {},
"className": "Layer",
"children": [{
"attrs": {
"text": "Hello world.",
"x": 50,
"y": 50,
"fontSize": 20,
"fill": "blue"
},
"className": "Text"
}]
}]

}

如您所见,我已经将src属性作为占位符,用于我们再次将数据加载到画布中。

我遇到的问题是,一旦我在服务器端处理 JSON,实际上就会再次加载这些图像。

这是我当前的代码

var fs = require('fs')
const Konva = require('konva-node')
var Request = require('pixl-request')
let json = {"attrs":{"width":600,"height":600},"className":"Stage","children":[{"attrs":{},"className":"Layer","children":[{"attrs":{"src":"https://ichef.bbci.co.uk/onesport/cps/480/cpsprodpb/1859A/production/_101883799_gettyimages-844211624.jpg"},"className":"Image"}]},{"attrs":{},"className":"Layer","children":[{"attrs":{"text":"Hello world.","x":50,"y":50,"fontSize":20,"fill":"blue"},"className":"Text"}]}] }
var stage = new Konva.Stage()
let loadedDesign = Konva.Node.create(json)

loadedDesign.find('Image').forEach((imageNode) => {
const imageURL = imageNode.getAttr('src')
var request = new Request();
request.get(imageURL, function(err, resp, data) {
var img = new Konva.window.Image()
img.onerror = err => { throw err }
img.onload = () => {
imageNode.image(img);
imageNode.getLayer().batchDraw();
}
img.src = data;
});
});
loadedDesign.toDataURL({
callback: function(data) {
var base64Data = data.replace(/^data:image/png;base64,/, '');
fs.writeFile('./images/out.png', base64Data, 'base64', function(err) {
err && console.log(err)
console.log('See out.png')
});
}
});

当前输出生成画布上带有文本的图像,但图像永远不会进入。

您需要加载所有图像,然后才使用toDataURL().我猜你的图像是不可见的,因为你在加载和撕裂图像之前将阶段转换为dataURL

var request = new Request();
function loadImage(url) {
return new Promise(resolve => {
request.get(url, function(err, resp, data) {
var img = new Konva.window.Image();
img.onerror = err => {
throw err;
};
img.onload = () => {
resolve(img);
};
img.src = data;
});
});
}
async function run() {
const stage = Konva.Node.create(json);
const images = stage.find('Image');
for (const imageNode of images) {
const imageURL = imageNode.getAttr('src');
const img = await loadImage(imageURL);
imageNode.setImage(img);
}
stage.findOne('Layer').draw();
const data = stage.toDataURL();
var base64Data = data.replace(/^data:image/png;base64,/, '');
fs.writeFile('out.png', base64Data, 'base64', function(err) {
err && console.log(err);
console.log('See out.png');
});
}
run().catch(e => {
console.error(e);
});

最新更新