【问题标题】:Saving current work from multiple canvas elements从多个画布元素保存当前工作
【发布时间】:2015-05-29 04:11:19
【问题描述】:

这是我的问题:我在 javascript 中创建了一个图像拼贴功能。 (顺便说一句,我从这篇文章中的一些代码开始:dragging and resizing an image on html5 canvas

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

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

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

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

function collage() {
  this.canvas_board = '';
  this.canvas = '';
  this.ctx = '';
  this.canvasOffset = '';
  this.offsetX = '';
  this.offsetY = '';
  this.startX = '';
  this.startY = '';
  this.imageX = '';
  this.imageY = '';
  this.mouseX = '';
  this.mouseY = '';
  this.imageWidth = '';
  this.imageHeight = '';
  this.imageRight = '';
  this.imageBottom = '';
  this.imgframe = '';
  this.frame = 'noframe';
  this.img = '';
  collage.instances.push(this);
}
collage.instances = [];

我尝试过这样的事情:

var oMyBlob = new Blob(collage.instances, {type: 'multipart/form-data'});

但这不起作用(仅包含大约 300 位数据)。

谁能帮忙?或者也许建议另一种方法来保存当前的拼贴作品。当然必须可以打开 blob 并重新填充对象实例。

或者也许我让这变得比它必须的复杂一点......但我现在被卡住了,所以我会很感激任何提示。

【问题讨论】:

  • 您可以在每个画布上 getImageData() 并保存该数据,或者您可以在每个画布上使用 canvas.getDataURL() 在保存之前转换为压缩格式。
  • 感谢您的回答。我正在尝试每个 toDataURL (也许这就是你的意思?)并使用 ajax 将数据发送到服务器端......虽然还没有。
  • 是的,我的意思是toDataURL(),我在下面的回答可以使用 ajax 以及保存本地文件。

标签: javascript html canvas


【解决方案1】:

您可以将每一层的图像数据提取到DataURLs并将结果保存为json对象。

这是一个快速演示:http://codepen.io/gunderson/pen/PqWZwW

该过程从字面上获取每个画布并保存其数据以供以后导入。

这里使用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;
}

要恢复,您可以使用 FileReader 将 JSON 的内容读回浏览器,然后为每一层设置 &lt;img&gt;s,将 img.src 设置为 JSON 中的 dataURL,然后您可以将&lt;img&gt; 绘制到onload 画布中。

【讨论】:

  • 感谢 jquery!我已经有了相同的结果 json 文件,但我现在更改了我的代码(借用了你的 getLayerData)。我现在在将层与 json.file 分开时有点挣扎……如果每个层都有一个键就好了。我正在尝试想出一些东西......
  • 知道了!由于数组没有键,但对象有,我只是做了这个小改动,以便能够通过结果文件中的键进行导航(抱歉不知道如何在此处格式化为代码):function getLayerData() { code: var imgData = {}; $("#board canvas").each(function(i, el) { imgData[i] = el.toDataURL("image/png"); }); console.log('imgdata ' + imgData); return imgData; }
【解决方案2】:

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

localStorage.setItem("currentwork", JSON.stringify(collage.instances));

那么要恢复你需要做的事情:

var tmp = localStorage.getItem("currentwork");
collage.instances = tmp ? JSON.parse(tmp) : [];

然后您需要遍历数组并使用正确的 onload 处理重新加载图像。最后重新渲染一切。

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

在服务器上保留指向图像的链接是 IMO 处理这些事情的更好方法。但是,如果您不同意,请查看 IndexedDB(或 WebSQL,尽管已弃用)以获得可以在可用空间中扩展的本地存储。 localStorage 只能容纳 2.5 - 5 mb,即。没有图像数据,只有字符串。每个 char 占用两个字节,data-uris 在顶部增加了 33%,所以这将很快运行为空...

【讨论】:

  • 我建议不要在本地存储图像,因为大多数浏览器只允许 ~2-3mb 的存储空间。
  • 感谢您编辑我的代码 sn-p,是的,我同意将数据发送到服务器端。我已经成功地将带有 ajax 的数据发送到服务器端,但我还没有弄清楚如何使用户可以访问该文件。也许最好使用普通的旧http。进行中
  • @ToJo_195 将具有广泛的兼容性。否则,如果您想将所有内容都保存在用户的浏览器上,IndexedDB 是一个不错的选择(尽管用户可能想要切换浏览器,或使用不同的计算机/设备等,所以在线存储可能是最好的选择)全部)。
  • @PatrickGunderson PNG 可以做成有损的(参见here),它使用 LZ77 压缩(连同扫描线过滤器),因此剔除低位有助于减小尺寸,但以质量为代价. Jpeg 将引入工件++ 是的,大小可能是一个问题,但是通过拆分最佳尺寸表的策略可以解决这个问题。 OP 没有说明图像有多大,如果用于打印,那么浏览器在任何情况下都不是最适合的,如果用于屏幕,拼贴应该提供太多问题,因为每个图像都会比屏幕小得多。
  • 我不知道结束这个问题。我不会把它称为“基于意见”,因为它是不具体的。我们提出了一些不同的解决方案,它们都可以满足原始问题。如果我们对应用程序有更多了解,我们最终可能会就存储数据的最佳方式/位置达成一致。
猜你喜欢
  • 2011-04-14
  • 2012-05-03
  • 2017-12-22
  • 2018-11-21
  • 2022-06-29
  • 2013-04-20
  • 1970-01-01
  • 2015-09-22
  • 2011-12-04
相关资源
最近更新 更多