Skip to content

Canvas 输出图片并下载

August 14, 2024 by ccforeverd

Canvas 输出图片并自动下载, 再使用浏览器标签快捷操作

代码部分

使用 blob 可以避免 base64 编码的图片过大, 从而导致无法下载的问题

download-canvas.ts
function downloadCanvas(element: HTMLCanvasElement, fileName = 'canvas.png') {
  const anchor = document.createElement('a');
  const pngBase64Data = element.toDataURL('image/png');
  // .replace('data:image/png;base64,', '')
  const blob = base64ToBlob(pngBase64Data);
  const url = URL.createObjectURL(blob);
 
  anchor.href = url;
  anchor.download = fileName;
  anchor.click();
 
  // URL.revokeObjectURL(url);
 
  function base64ToBlob(base64Data: string) {
    const byteString = atob(base64Data.replace('data:image/png;base64,', ''));
    const buffer = new ArrayBuffer(byteString.length);
    const view = new Uint8Array(buffer);
    for (let i = 0; i < byteString.length; i++) {
      view[i] = byteString.charCodeAt(i);
    }
    return new Blob([buffer], { type: 'image/png' });
  }
}

浏览器标签快捷操作

浏览器标签支持一行 javascript 代码, 可以添加书签并在 URL 内输入 javascript: 开头的代码

转换一下上面的代码

书签
 javascript:(() => { const script = document.createElement('script'); script.innerHTML = "function downloadCanvas(element, fileName = 'canvas.png') { const anchor = document.createElement('a'); const pngBase64Data = element.toDataURL('imagepng'); const blob = base64ToBlob(pngBase64Data); const url = URL.createObjectURL(blob); anchor.href = url; anchor.download = fileName; anchor.click(); function base64ToBlob(base64Data) { const byteString = atob(base64Data.replace('data:imagepng;base64,', '')); const buffer = new ArrayBuffer(byteString.length); const view = new Uint8Array(buffer); for (let i = 0; i < byteString.length; i++) { view[i] = byteString.charCodeAt(i); } return new Blob([buffer], { type: 'imagepng' }); }}"; document.body.appendChild(script); })();

逻辑是创建一个 script 标签, 然后将 downloadCanvas 注入到全局中, 然后在 console 中调用即可

使用方法:

  • 打开目标页面
  • 点击书签
  • 右键点击目标 canvas 元素, 选择 审查元素
  • 可以看到在 元素 选项卡中选中了目标 canvas 元素, 并且后面有一个 == $0 的提示
  • Esc 键, 弹出 console 控制台
  • 输入 downloadCanvas($0) 即可下载, 或者输入 downloadCanvas($0, '文件名.png') 指定文件名

问题

  1. 比如 figma 的预览, 下载的图片是全黑的, 可能是因为 figma 使用了 webgl 渲染, 无法直接下载, 需要使用 canvas 重新绘制
  2. 注入 script 时, 有可能会遇到报错: 是因为 CSP 的限制, 可以在 script 标签中添加 nonce 属性, 但是需要在 CSP 中添加对应的 nonce 值, 也可以使用 unsafe-inline 关键字, 但是不推荐