You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iPad端Chrome与Safari中canvas.toDataURL导出WebP失效问题求解

问题描述

使用canvas.toDataURL('image/webp', 0.8)处理图片时,安卓及Windows设备可正常生成WebP格式的DataURL,但在iPad(Safari 16.6、Chrome 130.0)上会默认返回PNG格式,canvas.toBlob()调用同样存在该问题。需求是实现所有设备(含苹果设备)将Canvas处理后的图片以WebP格式放入<img>标签中。

相关测试代码如下:

JavaScript

function doConvert() {
  const fileInput = document.querySelector("input[type='file']");
  const img = document.querySelector("img");
  const canvas = document.querySelector("canvas");
  const p = document.querySelector("p");
  const ctx = canvas.getContext("2d");

  const file = fileInput.files[0];

  if (file) {
    const reader = new FileReader();

    reader.onload = function (e) {
      const imgElement = new Image();
      imgElement.src = e.target.result;

      imgElement.onload = function() {
        // Set up the canvas size
        const width = imgElement.width;
        const height = imgElement.height;
        const dpr = window.devicePixelRatio || 1;

        canvas.width = width * dpr;
        canvas.height = height * dpr;

        // Apply scaling and draw image onto canvas
        ctx.scale(dpr, dpr);
        ctx.drawImage(imgElement, 0, 0, width, height);

        // Convert to WebP and display in the img element
        let dataUrl = canvas.toDataURL("image/webp", 0.8);
        img.src = dataUrl;

        p.innerHTML = navigator.userAgent+'&lt;HR&gt;'+dataUrl.substring(0,30)+'...'; // Logging the base64 string for reference
      };
    };

    reader.readAsDataURL(file);
  }
}

CSS

img, canvas {
  width:auto;
  height:50vh;
  vertical-align:top;  
}
canvas {
  border:solid 1px orange;
}
img {
  border:solid 1px red;  
}
div {
  margin:10px;
}

HTML

<input type="file" onChange="doConvert()" />
<div>canvas:<canvas></canvas> img:<img /></div>
<div>
  <p></p>
</div>
可行解决方案

1. 先检测浏览器的WebP导出支持

iOS 16.4+和macOS 13.3+的Safari理论上支持Canvas导出WebP,但部分场景存在兼容性bug。先通过代码检测当前环境是否支持原生WebP导出:

function supportsCanvasWebPExport() {
  const testCanvas = document.createElement('canvas');
  testCanvas.width = 1;
  testCanvas.height = 1;
  return testCanvas.toDataURL('image/webp').startsWith('data:image/webp');
}

2. 原生API结合Fallback方案

优先使用canvas.toBlob()(比toDataURL更高效),若原生导出失败,使用第三方库作为兜底:

function doConvert() {
  const fileInput = document.querySelector("input[type='file']");
  const img = document.querySelector("img");
  const canvas = document.querySelector("canvas");
  const p = document.querySelector("p");
  const ctx = canvas.getContext("2d");

  const file = fileInput.files[0];

  if (file) {
    const reader = new FileReader();

    reader.onload = function (e) {
      const imgElement = new Image();
      imgElement.src = e.target.result;

      imgElement.onload = function() {
        const width = imgElement.width;
        const height = imgElement.height;
        const dpr = window.devicePixelRatio || 1;

        canvas.width = width * dpr;
        canvas.height = height * dpr;
        ctx.scale(dpr, dpr);
        ctx.drawImage(imgElement, 0, 0, width, height);

        // 尝试原生WebP导出
        canvas.toBlob(function(blob) {
          if (blob && blob.type === 'image/webp') {
            img.src = URL.createObjectURL(blob);
            p.innerHTML = `${navigator.userAgent}<HR>data:image/webp;base64,...`;
          } else {
            // 原生导出失败,使用libwebp转换
            convertCanvasToWebP(canvas, function(webpBlob) {
              img.src = URL.createObjectURL(webpBlob);
              p.innerHTML = `${navigator.userAgent}<HR>data:image/webp;base64,...`;
            });
          }
        }, 'image/webp', 0.8);
      };
    };

    reader.readAsDataURL(file);
  }
}

3. 使用libwebp.js作为兜底转换

libwebp是Google官方的WebP编码库,可以将Canvas的像素数据编码为WebP格式,解决原生API不支持的场景:

  1. 下载libwebp的编译版本并引入到项目中
  2. 实现转换函数:
function convertCanvasToWebP(canvas, callback) {
  const ctx = canvas.getContext('2d');
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const { width, height, data } = imageData;

  // 使用libwebp的encodeAPI(具体参数可根据需求调整)
  WebP.encode(data, width, height, 0.8, function(encodedData) {
    const webpBlob = new Blob([encodedData], { type: 'image/webp' });
    callback(webpBlob);
  });
}

补充说明

  • iOS上的Chrome等第三方浏览器基于WebKit内核,因此兼容性和Safari一致
  • 使用URL.createObjectURL()生成的Blob URL,在页面卸载或不再使用时建议调用URL.revokeObjectURL()释放资源

内容的提问来源于stack exchange,提问作者abe1432181

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 05:44:57