导出图片的方法

1.导出图片

基础导出
 const dpr = Math.max(window.devicePixelRatio || 1, 3) // 建议2~3
      const captureElement = () => {
        html2canvas(element, {
          scale: dpr,
          useCORS: true, // 允许跨域图片
          allowTaint: true, // 允许跨域图片
          backgroundColor: '#fff',
          imageTimeout: 30000, // 增加图片加载超时时间到30秒
          logging: false, // 开启日志便于调试
          width: 1280, // 固定宽度
          height: 720, // 固定高度
          scrollX: 0, // 固定滚动位置
          scrollY: 0,
          windowWidth: 1280, // 固定窗口尺寸
          windowHeight: 720,
          onclone: function (clonedDoc) {
            // 在克隆的文档中处理图片
            const clonedElement =clonedDoc.getElementById('你的box-id')
            const images =clonedElement.querySelectorAll('img')

            images.forEach(img => {
              // 确保图片样式正确
              img.style.display = 'block'
              img.style.visibility = 'visible'
              img.style.opacity = '1'
              // 如果图片有跨域问题,尝试重新设置src
              if (img.crossOrigin === 'anonymous') {
                img.crossOrigin = 'anonymous'
              }
            })
          }
        }).then(canvas => {
		 // blob下载
          canvas.toBlob(blob => {
            const url = URL.createObjectURL(blob)
            const a = document.createElement('a')
            a.download = this.studioInfo?.name + '看板图片.png'
            a.href = url
            a.click()
            URL.revokeObjectURL(url)
          }, 'image/png', 1)
		   // 普通下载
          // const link = document.createElement('a')
          // link.download = 'representative_station.png'
          // link.href = canvas.toDataURL('image/png')
          // link.click()
          this.imgLoading = false
        }).catch(error => {
          console.error('截图失败:', error)
          this.imgLoading = false
        })
      }

图片加载完成后导出
const downloadImage=()=>{
 this.imgLoading = true
      const element = document.getElementById('你的box-id')
      const images = element.querySelectorAll('img')
      let loadedImages = 0
      // 检查所有图片是否加载完成
      const checkImagesLoaded = () => {
        loadedImages++
        if (loadedImages === images.length) {
          // 所有图片加载完成,开始截图
          captureElement()
        }
      }

      // 截图函数
      const dpr = Math.max(window.devicePixelRatio || 1, 3) // 建议2~3
      const captureElement = () => {
        html2canvas(element, {
          scale: dpr,
          useCORS: true, // 允许跨域图片
          allowTaint: true, // 允许跨域图片
          backgroundColor: '#fff',
          imageTimeout: 30000, // 增加图片加载超时时间到30秒
          logging: false, // 开启日志便于调试
          width: 1280, // 固定宽度
          height: 720, // 固定高度
          scrollX: 0, // 固定滚动位置
          scrollY: 0,
          windowWidth: 1280, // 固定窗口尺寸
          windowHeight: 720,
          onclone: function (clonedDoc) {
            // 在克隆的文档中处理图片
            const clonedElement = clonedDoc.getElementById('你的box-id')
            const images = clonedElement.querySelectorAll('img')

            images.forEach(img => {
              // 确保图片样式正确
              img.style.display = 'block'
              img.style.visibility = 'visible'
              img.style.opacity = '1'
              // 如果图片有跨域问题,尝试重新设置src
              if (img.crossOrigin === 'anonymous') {
                img.crossOrigin = 'anonymous'
              }
            })
          }
        }).then(canvas => {
          canvas.toBlob(blob => {
            const url = URL.createObjectURL(blob)
            const a = document.createElement('a')
            a.download = '图片名.png'
            a.href = url
            a.click()
            URL.revokeObjectURL(url)
          }, 'image/png', 1)
          // const link = document.createElement('a')
          // link.download = '图片名.png'
          // link.href = canvas.toDataURL('image/png')
          // link.click()
          this.imgLoading = false
        }).catch(error => {
          console.error('截图失败:', error)
          this.imgLoading = false
        })
      }

      // 为每个图片添加加载事件
      if (images.length > 0) {
        images.forEach(img => {
          if (img.complete) {
            checkImagesLoaded()
          } else {
            img.addEventListener('load', checkImagesLoaded)
            img.addEventListener('error', checkImagesLoaded) // 处理加载失败的情况
          }
        })
      } else {
        // 没有图片,直接截图
        captureElement()
      }
    }
图片加载完成后,一些背景图片没有加载,还是可能出现错乱,补充:loading
loading方法
// 等待图片加载(包含 <img> 与 CSS background-image)
    // options.strict=true: 仅当所有图片成功加载才结束,无超时;ignoreError=true 时,失败也算完成
    // options.strict=false: 成功或失败都算完成,并在超时后自动结束
    waitForImages(rootEl, options = { timeoutMs: 12000, strict: false, ignoreError: true }) {
      const { timeoutMs = 12000, strict = false, ignoreError = false } = options || {}
      const imgs = Array.from(rootEl.querySelectorAll('img'))
      const nodes = Array.from(rootEl.querySelectorAll('*'))
      // 提取所有 background-image 中的 URL(可能有多重背景)
      const bgUrls = nodes.flatMap(el => {
        const s = window.getComputedStyle(el)
        const bg = s && s.backgroundImage
        if (!bg || bg === 'none') return []
        const matches = bg.match(/url\(("|')?(.*?)\1\)/g) || []
        return matches.map(m => m.replace(/.*url\(("|')?(.*?)\1\).*/, '$2'))
      })
      // 去重
      const uniqueBgUrls = Array.from(new Set(bgUrls))
      if (!imgs.length && !uniqueBgUrls.length) return Promise.resolve()

      const imgTasks = imgs.map(img => {
        if (strict) {
          // 严格:默认必须成功;ignoreError=true 时,错误也算完成
          if (img.complete) {
            if (img.naturalWidth > 0) return Promise.resolve()
            return ignoreError ? Promise.resolve() : Promise.reject(new Error('image load error: ' + (img.src || '')))
          }
          return new Promise((resolve, reject) => {
            const onLoad = () => { cleanup(); resolve() }
            const onError = () => { cleanup(); ignoreError ? resolve() : reject(new Error('image load error: ' + (img.src || ''))) }
            const cleanup = () => {
              img.removeEventListener('load', onLoad)
              img.removeEventListener('error', onError)
            }
            img.addEventListener('load', onLoad, { once: true })
            img.addEventListener('error', onError, { once: true })
          })
        }
        // 宽松:成功或失败都算完成
        if (img.complete) return Promise.resolve()
        return new Promise(resolve => {
          const done = () => {
            img.removeEventListener('load', done)
            img.removeEventListener('error', done)
            resolve()
          }
          img.addEventListener('load', done, { once: true })
          img.addEventListener('error', done, { once: true })
        })
      })

      const bgTasks = uniqueBgUrls.map(src => {
        return new Promise((resolve, reject) => {
          const im = new Image()
          // 仅用于等待,不影响 html2canvas 的 CORS 配置
          im.onload = () => resolve()
          im.onerror = () => (ignoreError || !strict) ? resolve() : reject(new Error('bg image load error: ' + src))
          im.src = src
        })
      })

      if (strict) {
        // 严格模式:不设超时
        return Promise.all([...imgTasks, ...bgTasks])
      }

      // 宽松模式:带超时兜底
      return new Promise(resolve => {
        let finished = false
        const finish = () => { if (finished) return; finished = true; resolve() }
        const timer = setTimeout(finish, timeoutMs)
        Promise.all([...imgTasks, ...bgTasks]).then(() => { clearTimeout(timer); finish() })
      })
    }
使用
async handlePageChange(page) {
      this.boxLoading = true
      await this.$nextTick() // 关键:等新 DOM 渲染出来
      try {
        await this.waitForImages(this.$el, { timeoutMs: 12000, strict: false })
      } finally {
        this.boxLoading = false // 兜底关闭
      }
}
posted @ 2025-08-28 10:44  流云君  阅读(11)  评论(0)    收藏  举报