【问题标题】:Why do canvas.toBlob and canvas.toDataURL have different return types为什么 canvas.toBlob 和 canvas.toDataURL 有不同的返回类型
【发布时间】:2019-07-31 03:19:45
【问题描述】:

canvas.toBlob() 需要回调函数,但 canvas.toDataURL() 会同步返回结果。为什么有区别?这不是问题,但我非常好奇,我找不到解释为什么会这样。

【问题讨论】:

  • 是的,这有点奇怪,可能只是事情的结局。 (不过,异步在这里很重要,因为它让浏览器在编码期间不会阻塞 UI。)
  • canvas.toDataURL() 比 Blob() 标准化之前要旧得多。在此期间,人们意识到高分辨率图像和移动性能将极大地受益于 node.js 流行的异步接口,它允许主机环境在调度处理和处理 RAM 方面具有更大的灵活性,而不会停止或减慢页面的执行。几乎所有 Blob() 接口都是异步的。
  • @dandavis 您可以将其发布为答案,以便我投票吗?你的回答对我来说听起来很棒,让它成为一个答案会让其他人也赞成它
  • @dandavis Virtually all Blob() interfaces are async Blob 构造函数和任何 Blob 方法除外?
  • @Kaiido:是的,使用 Blob 的接口是异步的:FileReader、Fetch 等...

标签: javascript html html5-canvas todataurl


【解决方案1】:

因为toDataURL 是一个早期错误...

在实现它时(由 Safari IIRC),FileAPI 仍然只是在讨论中,并且已经需要导出画布的结果。所以他们制作了这个方法,它确实在一个方便的数据 URL 中返回数据,您可以直接将其用作文档中多个元素的src。此时,同步返回它听起来是个好主意,Canvas API 中的所有内容都是同步的。

但几年后,随着越来越多的实现、越来越多的使用和新的 API,toDataURL 显然不是一个好主意。就像同步 XHR 一样,如果您足够大,可以记住。
即使您可以以同步方式拥有数据 URL,但无论如何显示它都是一个异步任务。

从画布生成图像文件是一项缓慢的操作,您需要导出所有像素数据,取消相乘,然后调用压缩算法。

除此之外,数据 URL 需要存储为 base64 编码的字符串,比它所代表的二进制数据大 34%,并且每次在 DOM 中的某个位置分配它时都会复制到内存中......

FileAPI 引入了将二进制数据保存在内存中并能够显示、操作或将其按原样发送到服务器的方法。所有这些都意味着最小的内存开销 => 数据 URL 变得过时(在大多数情况下)。

因此决定添加一个新方法,该方法将利用这些新 API,并返回 Blob 而不是数据 URL。在与 UI 阻塞操作的共同斗争中,已经决定这种方法将是异步的(但不幸的是,那是在 Promise 出现之前...)。现在所有必须同步完成的就是抓取像素数据,就像getImageData 所做的那样。其余操作可以并行完成。

【讨论】:

  • 这一切都很好,花花公子,直到您遇到浏览器故意施加给您的其他限制,例如触发下载必须与用户点击事件同步发生。例如,您将诸如 toBlob 之类的异步调用混入其中,Safari 会阻止您。这是一个好主意,但它突然不是。
  • @user2867288 他们需要在哪个平台上下载作为用户手势的一部分?在 macOS 上,他们清楚地允许从不在 DOM 中的元素进行此操作。无论如何,用户手势应该存在几毫秒,你的画布真的那么大,需要几毫秒才能导出吗?
  • iOS。不是需要多长时间,而是异步即使需要1毫秒,你就失去了对点击事件的信任。
  • 这太出乎意料了...根据规范应该有一个"transient activation duration",即使他们没有定义下限,最后我检查了所有同意至少几毫秒的UA。
  • 是的。关于您的评论“您的画布真的那么大吗?需要几毫秒才能导出”,即使是 4k 画布也需要几秒钟,而不是几毫秒才能转换为中档笔记本电脑上的 blob。不应在任意时间范围内编写规范。
猜你喜欢
  • 1970-01-01
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
  • 2010-12-07
  • 2023-03-19
  • 2016-08-30
  • 2021-06-06
  • 1970-01-01
相关资源
最近更新 更多