导出图片的方法
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 // 兜底关闭
}
}
本文来自博客园,作者:流云君,转载请注明原文链接:https://www.cnblogs.com/yun10011/p/19062176

浙公网安备 33010602011771号