// 这是在renderjs中使用的
export const draw = async (instance: any, referenceId = '#reference', outputId = '#output') => {
// 等待字体加载完成
await document.fonts.load('12px share-title')
await document.fonts.load('12px share-sub-title')
await document.fonts.load('12px iconfont')
// 获取对比容器
const reference = document.querySelector(referenceId)
// 开始绘制
// @ts-ignore
html2canvas(reference, { allowTaint: true, useCORS: true, logging: true }).then((canvas: HTMLCanvasElement) => {
const output = document.querySelector(outputId) as HTMLDivElement
const outputCanvas = output.querySelector('canvas') as HTMLCanvasElement
const ctx = outputCanvas.getContext('2d', { willReadFrequently: true })!
const pixelRatio = window.devicePixelRatio
const width = canvas.width / pixelRatio
const height = canvas.height / pixelRatio
// 设置画布宽高
output.style.width = width / pixelRatio + 'px'
output.style.height = height / pixelRatio + 'px'
outputCanvas.height = height
outputCanvas.width = width
ctx.clearRect(0, 0, width, height)
// 将绘制完成的 canvas 放入 uniapp 组件的 canvas
ctx.drawImage(canvas, 0, 0, Math.ceil(width / pixelRatio), Math.ceil(height / pixelRatio))
instance.$ownerInstance.callMethod('changeLoading')
})
}

- 发布:2023-03-12 23:57
- 更新:2023-03-13 11:11
- 阅读:342
产品分类: uniapp/App
PC开发环境操作系统: Windows
PC开发环境操作系统版本号: 11
HBuilderX类型: 正式
HBuilderX版本号: 3.7.6
手机系统: Android
手机系统版本号: Android 10
手机厂商: 小米
手机机型: Redmi Note 9
页面类型: vue
vue版本: vue3
打包方式: 云端
项目创建方式: HBuilderX
示例代码:
操作步骤:
1.DOM 模板
<div>
<div
id="reference"
class="absolute top-0 left-0 w-full bg-cover bg-no-repeat h-[100vh]"
>
<image src="/static/images/default.png" alt="" />
</div>
<canvas id="output" canvas-id="output-canvas"></canvas>
</div>
2.使用 renderjs 模块
<script module="render" lang="renderjs">
import { draw } from '@/utils/share'
export default {
methods: {
async updateData(modelValue) {
if (modelValue) { draw(this) }
}
},
}
</script>
3.基于渲染的 dom 元素 渲染成为 canvas
// 这是在renderjs中使用的
export const draw = async (instance: any, referenceId = '#reference', outputId = '#output') => {
// 等待字体加载完成
await document.fonts.load('12px share-title')
await document.fonts.load('12px share-sub-title')
await document.fonts.load('12px iconfont')
// 获取对比容器
const reference = document.querySelector(referenceId)
// 开始绘制
// @ts-ignore
html2canvas(reference, { allowTaint: true, useCORS: true, logging: true }).then((canvas: HTMLCanvasElement) => {
const output = document.querySelector(outputId) as HTMLDivElement
const outputCanvas = output.querySelector('canvas') as HTMLCanvasElement
const ctx = outputCanvas.getContext('2d', { willReadFrequently: true })!
const pixelRatio = window.devicePixelRatio
const width = canvas.width / pixelRatio
const height = canvas.height / pixelRatio
// 设置画布宽高
output.style.width = width / pixelRatio + 'px'
output.style.height = height / pixelRatio + 'px'
outputCanvas.height = height
outputCanvas.width = width
ctx.clearRect(0, 0, width, height)
// 将绘制完成的 canvas 放入 uniapp 组件的 canvas
ctx.drawImage(canvas, 0, 0, Math.ceil(width / pixelRatio), Math.ceil(height / pixelRatio))
instance.$ownerInstance.callMethod('changeLoading')
})
}
1.DOM 模板
<div>
<div
id="reference"
class="absolute top-0 left-0 w-full bg-cover bg-no-repeat h-[100vh]"
>
<image src="/static/images/default.png" alt="" />
</div>
<canvas id="output" canvas-id="output-canvas"></canvas>
</div>
2.使用 renderjs 模块
<script module="render" lang="renderjs">
import { draw } from '@/utils/share'
export default {
methods: {
async updateData(modelValue) {
if (modelValue) { draw(this) }
}
},
}
</script>
3.基于渲染的 dom 元素 渲染成为 canvas
// 这是在renderjs中使用的
export const draw = async (instance: any, referenceId = '#reference', outputId = '#output') => {
// 等待字体加载完成
await document.fonts.load('12px share-title')
await document.fonts.load('12px share-sub-title')
await document.fonts.load('12px iconfont')
// 获取对比容器
const reference = document.querySelector(referenceId)
// 开始绘制
// @ts-ignore
html2canvas(reference, { allowTaint: true, useCORS: true, logging: true }).then((canvas: HTMLCanvasElement) => {
const output = document.querySelector(outputId) as HTMLDivElement
const outputCanvas = output.querySelector('canvas') as HTMLCanvasElement
const ctx = outputCanvas.getContext('2d', { willReadFrequently: true })!
const pixelRatio = window.devicePixelRatio
const width = canvas.width / pixelRatio
const height = canvas.height / pixelRatio
// 设置画布宽高
output.style.width = width / pixelRatio + 'px'
output.style.height = height / pixelRatio + 'px'
outputCanvas.height = height
outputCanvas.width = width
ctx.clearRect(0, 0, width, height)
// 将绘制完成的 canvas 放入 uniapp 组件的 canvas
ctx.drawImage(canvas, 0, 0, Math.ceil(width / pixelRatio), Math.ceil(height / pixelRatio))
instance.$ownerInstance.callMethod('changeLoading')
})
}
预期结果:
预期结果是可以下载canvas的文件
预期结果是可以下载canvas的文件
实际结果:
23:31:24.457 [TIP] :#1 0ms Starting document clone with size 394x804 scrolled to 0,0 at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.181 [TIP] :#1 722ms Document cloned, element located at -394.18182373046875,0 with size 394.18182373046875x700 using computed rendering at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.190 [TIP] :#1 722ms Starting DOM parsing at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.245 [TIP] :#1 782ms Added image file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/static/images/default.png at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.261 [TIP] :#1 799ms Starting renderer for element at -394.18182373046875,0 with size 395x700 at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.263 [TIP] :#1 800ms Canvas renderer initialized (395x700) with scale 2.75 at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.308 [TIP] :#1 850ms Finished rendering at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.324 Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
Error: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
at o (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:155807)
at Ea (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29262)
at Ca (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29339)
at qa (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:31263)
at file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:151322
at Ea (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29262)
at Ca (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29339)
at _ (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:34185)
at Ea (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29270)
at Ua (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:30772) at uni-app-view.umd.js:1
23:31:24.457 [TIP] :#1 0ms Starting document clone with size 394x804 scrolled to 0,0 at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.181 [TIP] :#1 722ms Document cloned, element located at -394.18182373046875,0 with size 394.18182373046875x700 using computed rendering at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.190 [TIP] :#1 722ms Starting DOM parsing at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.245 [TIP] :#1 782ms Added image file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/static/images/default.png at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.261 [TIP] :#1 799ms Starting renderer for element at -394.18182373046875,0 with size 395x700 at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.263 [TIP] :#1 800ms Canvas renderer initialized (395x700) with scale 2.75 at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.308 [TIP] :#1 850ms Finished rendering at https://img.coregem.net/js/html2canvas.min.js:22
23:31:25.324 Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
Error: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
at o (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:155807)
at Ea (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29262)
at Ca (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29339)
at qa (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:31263)
at file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:151322
at Ea (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29262)
at Ca (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29339)
at _ (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:34185)
at Ea (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29270)
at Ua (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:30772) at uni-app-view.umd.js:1
bug描述:
- 使用 renderjs + html2canvas 在App端引入本地图片渲染报错
Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
Error: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
at o (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:155807)
at Ea (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29262)
at Ca (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29339)
at qa (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:31263)
at file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:151322
at Ea (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29262)
at Ca (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29339)
at _ (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:34185)
at Ea (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:29270)
at Ua (file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/www/uni-app-view.umd.js:1:30772) at uni-app-view.umd.js:1



1***@qq.com (作者)
在 红米K20pro 上可以正常使用canvasToTempFilePath函数,只有某些手机中报这个错误
// 这个是保存的逻辑
const saveImage = () => {
uni.showLoading({ title: '保存中' })
typeof canvasId === 'function' ? (canvasId = canvasId()) : null
uni.canvasToTempFilePath(
{
canvasId,
success({ tempFilePath }) {
// #ifdef H5
downloadImage(tempFilePath)
// #endif
// #ifdef APP-PLUS
saveImageToApp(tempFilePath)
// #endif
},
fail(r) {
uni.hideLoading()
console.log(r)
uni.showToast({ title: '保存失败', icon: 'none' })
},
},
instance,
)
}