Javascript 从多个画布元素保存当前工作

Javascript 从多个画布元素保存当前工作,javascript,html,canvas,Javascript,Html,Canvas,这是我的问题:我用javascript创建了一个图像拼贴函数。(我从这篇文章的一些代码开始,顺便说一句:) 我有10个画布元素堆叠在一起,所有参数,包括2dcontext、图像数据、位置等,每个画布都保存在函数“拼贴”的实例中 这很好,我可以分别操纵每个画布(拖动、调整大小、添加帧等)。但是现在,我希望用户能够保存当前的工作 所以我想,也许可以创建一个包含所有对象实例的blob,然后将该blob保存为磁盘上的文件 这是函数拼贴(我还将每个实例推送到数组collage.instances,以便能够

这是我的问题:我用javascript创建了一个图像拼贴函数。(我从这篇文章的一些代码开始,顺便说一句:)

我有10个画布元素堆叠在一起,所有参数,包括2dcontext、图像数据、位置等,每个画布都保存在函数“拼贴”的实例中

这很好,我可以分别操纵每个画布(拖动、调整大小、添加帧等)。但是现在,我希望用户能够保存当前的工作

所以我想,也许可以创建一个包含所有对象实例的blob,然后将该blob保存为磁盘上的文件

这是函数拼贴(我还将每个实例推送到数组collage.instances,以便能够有编号的索引)

函数拼贴(){
此.canvas_板=“”;
这个.canvas='';
this.ctx=“”;
this.canvasOffset='';
this.offsetX='';
this.offsetY='';
this.startX='';
this.startY='';
this.imageX='';
this.imageY='';
this.mouseX='';
this.mouseY='';
此参数为.imageWidth='';
此.imageHeight='';
this.imageRight='';
this.imageBottom='';
this.imgframe='';
this.frame='noframe';
this.img='';
拼贴.实例.推(此);
}
collage.instances=[];
我试过这样的方法:

var oMyBlob = new Blob(collage.instances, {type: 'multipart/form-data'});
但这不起作用(只包含大约300位数据)

有人能帮忙吗?或者建议另一种方法来保存当前的拼贴工作。当然,必须能够打开blob并重新填充对象实例

或者我把事情弄得比实际情况更复杂了。。。但是我现在被卡住了,所以我希望得到任何提示。

将映像的引用(src URL)添加到实例中,然后将实例数组序列化为JSON并使用f.ex。本地存储

localStorage.setItem("currentwork", JSON.stringify(collage.instances));
然后,要恢复,您需要执行以下操作:

var tmp = localStorage.getItem("currentwork");
collage.instances = tmp ? JSON.parse(tmp) : [];
然后,您需要遍历数组,并使用适当的onload处理重新加载图像。最后重新渲染所有内容

您可以在客户端上存储图像数据吗?是的,但不推荐。这将占用大量空间,如果太多,您将无法保存所有数据,用户可能会拒绝提供更多存储空间等


在服务器上保留指向映像的链接是解决这些问题的更好方法。但如果您不同意,请查看IndexedDB(或WebSQL,尽管已弃用),以获得可以在可用空间中扩展的本地存储。localStorage只能容纳2.5-5 mb,即没有图像数据,只有字符串。每个字符占用两个字节,数据URI在顶部添加33%,因此这将很快空运行…

您可以将每个层的图像数据提取到DataURL,并将结果保存为json对象

下面是一个快速演示:

该过程会逐字提取每个画布,并保存其数据以供以后导入

这里使用jquery是为了方便:

$(".save-button").click(function() {
  var imgData = JSON.stringify({
    layers: getLayerData()
  });
  save(imgData, "myfile.json");
});

function save(filecontents, filename) {
  try {
    var $a = $("<a>").attr({
      href: "data:application/json;," + filecontents,
      download: filename
    })[0].click();
    return filecontents;
  } catch (err) {
    console.error(err);
    return null;
  }
}

function getLayerData() {
  var imgData = [];
  $(".layer").each(function(i, el) {
    imgData.push(el.toDataURL("image/png"));
  });
  return imgData;
}
$(“.save按钮”)。单击(函数(){
var imgData=JSON.stringify({
图层:getLayerData()
});
保存(imgData,“myfile.json”);
});
函数保存(文件内容、文件名){
试一试{
变量$a=$(“”)。属性({
href:“数据:应用程序/json;,”+文件内容,
下载:文件名
})[0]。单击();
返回文件内容;
}捕捉(错误){
控制台错误(err);
返回null;
}
}
函数getLayerData(){
var imgData=[];
$(“.layer”)。每个(函数(i,el){
imgData.push(el.toDataURL(“image/png”);
});
返回imgData;
}

要恢复,您可以使用
文件读取器
将JSON的内容读回浏览器,然后将
读入JSON中的数据URL,从那里您可以将
读入
onload
画布

您可以在每个画布上获取ImageData()并保存该数据,也可以从每个画布上获取canvas.getDataURL(),以便在保存之前转换为压缩格式。感谢您的回答。我正在尝试在每个服务器上使用toDataURL(也许这就是你的意思?),并使用ajax将数据发送到服务器端。。。不过还没有。是的,我的意思是
toDataURL()
,我下面的答案可以与ajax一起使用,就像保存本地文件一样。我建议不要使用本地存储,因为大多数浏览器只允许2-3mb的存储空间。感谢您编辑我的代码片段,是的,我同意将数据发送到服务器端。我已经成功地使用ajax将数据发送到服务器端,但是我还没有弄清楚如何让用户可以访问该文件。也许最好使用普通的旧http。从事progress@ToJo_195这将具有广泛的兼容性。否则,如果您想在用户浏览器上本地保存所有内容,IndexedDB是一个很好的选择(尽管用户可能希望切换浏览器,或使用不同的计算机/设备等,因此在线存储可能是最好的选择)。@PatrickGunderson PNG可以设置为有损(请参阅),并使用LZ77压缩(连同扫描线过滤器)因此,去掉较低的位有助于减小大小,但会降低质量。Jpeg会引入瑕疵++是的,大小可能是一个问题,但通过策略拆分最佳大小的纸张可以解决这一问题。OP没有说明图像有多大,如果用于打印,那么浏览器在任何情况下都不是最适合的,如果用于屏幕颜色lage应该会带来太多的问题,因为每张图像都会比屏幕小得多。我不知道如何结束这个问题。我不会称它为“基于意见的”具体来说,我们已经提出了一些不同的解决方案,这些解决方案都满足了最初的问题。如果我们对应用程序了解更多,我们可能最终都会就存储数据的最佳方式/位置达成一致。感谢jquery!我已经有了相同的json文件,但我现在已经更改了代码(借用了你的getLayerData)。我现在正在努力将层从json.file中分离出来……最好每个层都有一个键。