前端截图新思路:使用 html2canvas

624 阅读5分钟

在现代 Web 开发中,图表可视化已成为数据呈现的重要方式。然而,有时我们不仅需要展示完整的图表,还需要生成图表的缩略图用于列表展示或预览。ECharts 提供了 getDataURL 方法可以导出图表图片,但如果图表不仅仅是 ECharts,还包含其他 HTML 元素,那么 html2canvas 就成为一个非常实用的工具。本文将介绍如何使用 html2canvas 库,获取图表区域的截图,并将其转换为缩略图。

什么是 html2canvas?

html2canvas 是一个 JavaScript 库,可以将 HTML 元素渲染成 Canvas 图像。它能够获取 DOM 元素的视觉表示,并将其绘制到 <canvas> 元素上。这为前端生成截图、实现自定义渲染提供了强大的能力。

项目场景:

假设你有一个图表区域,它可能包含 ECharts 图表、文本标签、自定义图形等各种 HTML 元素,你需要生成这个区域的缩略图,以便在其他地方进行预览或展示。

核心代码详解:

以下代码是文章的关键部分,解释了如何使用 html2canvas 生成缩略图,并将其转换为 File 对象:

// 假设你已经通过某种方式获取到了图表区域的 DOM 元素,例如:
// const range = document.querySelector('.data-canvas') as HTMLElement;

/**
 * 获取缩略图片
 * @param {HTMLElement} range 需要截图的 DOM 元素
 * @returns {Promise<File>} 缩略图的 File 对象
 */
const getThumbnail = async (range: HTMLElement): Promise<File> => {
  // 使用 html2canvas 生成图片
  const canvasImage: HTMLCanvasElement = await html2canvas(range, {
    backgroundColor: null, // 设置背景色为透明
    allowTaint: true, // 允许跨域资源污染
    useCORS: true,    // 允许跨域请求
    scale: 0.2, // 添加缩放比例 0.2 表示缩小为 20%
  });

  // 将 Canvas 转换为 base64 编码的图片数据
  const base64Img = canvasImage.toDataURL('image/png');

    // 将 base64 编码的图片数据转换为 File 对象
    const fileImg = base64toFile(base64Img, generateUUID());

    return fileImg;
};

/**
 * 将 base64 编码的图片数据转换为 File 对象
 * @param {string} base64  base64 编码的图片数据
 * @param {string} filename 文件名
 * @returns {File} File 对象
 */
function base64toFile(base64: string, filename: string): File {
  const arr = base64.split(',');
  const mime = arr[0].match(/:(.*?);/)?.[1];
  const bstr = atob(arr[1]);
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], filename, { type: mime || 'image/png' });
}

/**
 * 生成唯一 ID (UUID)
 * @returns {string} 唯一 ID
 */
function generateUUID(): string {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = (Math.random() * 16) | 0,
      v = c == 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
}

// 调用 getThumbnail 函数,并传入图表区域的 DOM 元素
// getThumbnail(document.querySelector('.data-canvas') as HTMLElement)
//   .then(file => {
//     console.log('缩略图 File 对象:', file);
//     // 这里可以处理 File 对象,例如上传到服务器
//   });

代码详解:

  1. getThumbnail(range: HTMLElement) 函数:

    • 接受一个 HTML 元素 range 作为参数,该元素是你想要截图的图表区域的 DOM 元素。

    • 使用 async 和 await 确保异步操作按顺序执行。

    • 调用 html2canvas(range, options) 生成 Canvas 图像。

      • backgroundColor: null: 设置背景色为透明,这样可以避免生成图片时出现白色背景。
      • allowTaint: true: 允许跨域资源污染,处理某些图片加载失败的情况。
      • useCORS: true: 允许跨域请求,确保图片资源可以正常加载。
      • scale: 0.2: 添加 scale 选项, 表示缩小为 20%,生成缩略图效果。 可以根据需要调整缩放比例。
    • 将 canvas 元素转换为 base64 编码的 PNG 图片数据。

    • 调用 base64toFile() 将 base64 编码的图片数据转换为 File 对象。

    • 返回 File 对象。

  2. base64toFile(base64: string, filename: string) 函数:

    • 接受 base64 编码的图片数据和 filename 作为参数。
    • 将 base64 数据解码为 Uint8Array
    • 创建一个新的 File 对象,包含 Uint8Array 数据、文件名和图片类型。
    • 返回 File 对象。
  3. generateUUID() 函数:

    • 生成唯一 ID (UUID)。
    • 用于生成文件名, 避免文件名冲突。

优势和适用场景:

  • 通用性强:  html2canvas 不仅可以用于 ECharts 图表,还可以用于任何 HTML 元素的截图,具有很好的通用性。
  • 自定义程度高:  你可以控制截图的各种参数,例如背景色、缩放比例等。
  • 缩略图生成:  通过 scale 选项 可以直接生成缩略图。
  • 灵活性:  可以通过修改 scale 选项,实现不同大小的缩略图。
  • 无需服务器:  整个过程在客户端完成,无需服务器支持。
  • 适用场景:  适用于需要生成复杂 HTML 元素截图、需要在前端生成缩略图等各种场景。

注意事项:

  • 跨域问题:  如果图表区域使用了跨域资源,需要配置 allowTaint: true 和 useCORS: true
  • 渲染性能:  如果要截图的区域非常复杂,可能会影响渲染性能,可以尝试使用 setTimeout 分批渲染。
  • 兼容性:  html2canvas 的兼容性较好,但在某些老版本浏览器上可能存在一些问题。
  • 图像质量:  如果缩放比例太小,可能会导致缩略图模糊。

总结:

html2canvas 是一个非常实用的前端截图工具,它可以帮助你轻松地获取图表区域的截图,并将其转换为缩略图。 在实际项目中,你可以根据需要调整代码,例如添加进度条,优化截图的质量等。 希望本文能帮助你更好地理解 html2canvas 的使用方法,并在你的项目中灵活应用。