Vue3+Element Plus项目中使用html2canvas截图方式

 更新时间:2026年03月23日 09:19:16   作者:Mr Xu_  
这篇文章主要介绍了Vue3+Element Plus项目中使用html2canvas截图方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

在现代 Web 应用开发中,常常需要将页面中的某一部分内容生成图片,用于保存、打印或上传。html2canvas 是一个非常流行的前端库,它能将 HTML 元素“绘制”成 Canvas,进而导出为图片。

本文将结合实际 Vue3 + Element Plus 项目代码,深入剖析 html2canvas 的使用方法及常见注意事项。

一、项目背景

我们有一个考核表单页面(TotalExamine.vue),用户填写考核信息后,系统需将下方的评分表格区域自动截图,并作为附件上传至服务器。

该功能的核心就是利用 html2canvas 对指定 DOM 区域进行截图。

二、核心代码分析

1. 引入依赖

import html2canvas from 'html2canvas'

确保已在项目中安装:

npm install html2canvas

2. 指定截图区域

通过 ref 获取需要截图的 DOM 元素:

<template>
  <div class="bottomContainer" id="superMap" ref="imageContentRef">
    <!-- 表格内容 -->
    <el-table :data="tableData">...</el-table>
  </div>
</template>

<script setup>
const imageContentRef = ref(null)
</script>

关键点ref="imageContentRef" 绑定到需要截图的容器上。

3. 触发截图并上传

在提交按钮点击事件 handleSubmitFinal() 中执行截图逻辑:

async function handleSubmitFinal() {
  formRef.value.validate(async valid => {
    if (valid) {
      // 1. 使用 html2canvas 截图
      const canvas = await html2canvas(imageContentRef.value)

      // 2. 将 canvas 转为 Blob
      canvas.toBlob(async (blob) => {
        // 3. 创建 File 对象
        const file = new File([blob], '考核成绩.png', { type: 'image/png' })

        // 4. 构造 FormData 用于上传
        const uploadForm = new FormData()
        uploadForm.append('file', file)

        // 5. 调用上传接口
        const res = await getOverallExamineUpload(uploadForm)
        const fileId = res?.data[0].fileId

        // 6. 提交完整表单数据(含 fileId)
        const data = { ...formInline, fileId }
        const resp = await getOverallExamineSave(data)
        if (resp.code === 200) {
          ElMessage.success('提交成功!')
        }
      }, 'image/png')
    }
  })
}

流程清晰:验证 → 截图 → 转文件 → 上传 → 提交主数据。

三、使用 html2canvas 的注意事项(避坑指南)

1.异步渲染问题

html2canvas 是基于当前 DOM 状态截图的。如果目标区域包含动态加载的内容(如表格数据异步获取),必须确保 DOM 已完全渲染后再调用。

解决方案

  • 使用 nextTick() 确保 DOM 更新完成。
  • 或在数据加载完成后再触发截图。

在本例中,tableData 是静态初始化的,所以无此问题。但若从 API 获取,需加 await nextTick()

2.跨域图片无法渲染

如果截图区域内包含 <img> 标签且图片来自其他域名(如 CDN),默认情况下 html2canvas 会因 CORS 策略将其渲染为空白。

解决方案

  • 图片服务器需设置 Access-Control-Allow-Origin
  • 或使用代理加载图片。
  • 或提前将图片转为 base64 内联。

本例未使用外部图片,故安全。

3.CSS 样式兼容性

html2canvas 并非 100% 支持所有 CSS 属性。例如:

  • box-shadowtransformfilter 可能失效。
  • position: fixed 元素可能错位。
  • 自定义字体(如 iconfont)可能显示为方块。

建议

  • 尽量使用基础样式。
  • 截图前可临时添加 .screenshot-mode 类,覆盖复杂样式。
  • 测试不同浏览器表现。

本项目使用 Element Plus 默认样式,兼容性较好。

4.容器尺寸与滚动

若截图区域有滚动条(如 el-table 设置了 height),html2canvas 默认只截取可视区域。

解决方案

  • 确保容器高度足够容纳全部内容(如本例中 .bottomContainer 高度由父级控制)。
  • 或临时修改容器样式(如 overflow: visible)再截图。

⚠️ 5.Canvas 转 Blob 的兼容性

canvas.toBlob() 在部分旧浏览器(如 IE)不支持。

Polyfill 方案

if (!HTMLCanvasElement.prototype.toBlob) {
  Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
    value: function (callback, type, quality) {
      const binStr = atob(this.toDataURL(type, quality).split(',')[1])
      const arr = new Uint8Array(binStr.length)
      for (let i = 0; i < binStr.length; i++) {
        arr[i] = binStr.charCodeAt(i)
      }
      callback(new Blob([arr], { type: type || 'image/png' }))
    }
  })
}

现代项目通常无需考虑,但需知晓。

四、优化建议

截图前隐藏无关元素

可临时隐藏按钮、滚动条等干扰项:

const el = imageContentRef.value
el.querySelector('.no-print')?.style.display = 'none'

提升截图清晰度

通过缩放提高分辨率:

const scale = window.devicePixelRatio || 2
const canvas = await html2canvas(el, { scale })

错误处理

添加 try-catch 防止截图失败导致整个流程中断。

五、总结

html2canvas 是实现前端“所见即所得”截图的强大工具。在 Vue3 项目中,结合 refasync/await 可轻松集成。但务必注意其局限性,尤其是在样式兼容性和异步渲染方面。

通过本文的代码分析与注意事项梳理,相信你能在自己的项目中更稳健地使用 html2canvas,避免踩坑,高效交付功能!

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Vue.js中轻松解决v-for执行出错的三个方案

    Vue.js中轻松解决v-for执行出错的三个方案

    v-for标签可以用来遍历数组,将数组的每一个值绑定到相应的视图元素中去,下面这篇文章主要给大家介绍了关于在Vue.js中轻松解决v-for执行出错的三个方案,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-06-06
  • vue中$router.back()和$router.go()的用法

    vue中$router.back()和$router.go()的用法

    这篇文章主要介绍了vue中$router.back()和$router.go()的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • 动态Axios的配置步骤详解

    动态Axios的配置步骤详解

    这篇文章主要给大家分享介绍了关于动态Axios的配置步骤,文中通过示例代码介绍的非常详细,通过这个教程大家可以很方便的实现动态Axios的配置,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
    2018-01-01
  • vue删除html内容的标签样式实例

    vue删除html内容的标签样式实例

    今天小编就为大家分享一篇vue删除html内容的标签样式实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • 详解Vue2.x-directive的学习笔记

    详解Vue2.x-directive的学习笔记

    这篇文章主要介绍了详解Vue2.x-directive的学习笔记,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • vue3使用video.js播放m3u8格式视频的操作指南

    vue3使用video.js播放m3u8格式视频的操作指南

    有时候我们需要播放 m3u8 格式的视频,或者实现视频播放器更多定制化需求,HTML 的 video 元素无法实现这些需求,这时候可以考虑使用 Video.js,本文给大家介绍了vue3使用video.js播放m3u8格式视频的操作指南,需要的朋友可以参考下
    2024-07-07
  • element中el-table与el-form同用并校验

    element中el-table与el-form同用并校验

    本文主要介绍了element中el-table与el-form同用并校验,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • vue3响应式Object代理对象的读取示例详解

    vue3响应式Object代理对象的读取示例详解

    这篇文章主要为大家介绍了vue3响应式Object代理对象的读取示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • 详解Vue方法与事件

    详解Vue方法与事件

    本篇文章主要介绍了详解Vue方法与事件。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • vue组件引用另一个组件出现组件不显示的问题及解决

    vue组件引用另一个组件出现组件不显示的问题及解决

    这篇文章主要介绍了vue组件引用另一个组件出现组件不显示的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04

最新评论