解决 "Tainted canvases may not be exported" 的问题与 Konva
当你尝试导出画布时,可能会遇到以下错误:
无法获取数据 URL。无法在 'HTMLCanvasElement' 上执行 'toDataURL':污染的画布无法导出。
无法从画布获取图像数据,因为画布被跨域数据污染了。
或者当你应用过滤器时,可能会出现以下错误:
无法应用过滤器。无法在 'CanvasRenderingContext2D' 上执行 'getImageData':画布已经被跨域数据污染。
无法应用过滤器。操作不安全。
为什么会出现这个不安全的错误?
这是一个 CORS 错误。出于安全原因,当你从另一个域加载图像时,浏览器会将画布标记为污染。在这种情况下,浏览器会阻止将画布导出为 dataURL
或 imageData
(这就是我们在导出或使用过滤器时所做的)。
如何解决 CORS 问题?
首先,你可以尝试设置正在加载的图像的 crossOrigin = Anonymous
属性。此方法仅在请求的域具有允许共享请求的 Access-Control-Allow-Origin
头时有效。
- Vanilla
- React
- Vue
import Konva from 'konva';
// 方法 1:原生图像加载
const imageObj = new Image();
imageObj.onload = () => {
const image = new Konva.Image({
x: 50,
y: 50,
image: imageObj
});
layer.add(image);
};
imageObj.crossOrigin = 'Anonymous';
imageObj.src = url;
// 方法 2:使用 Konva 帮助方法
// crossOrigin 会自动设置为 Anonymous
Konva.Image.fromURL(url, (image) => {
image.setAttrs({
x: 50,
y: 50
});
layer.add(image);
});
import { Stage, Layer, Image } from 'react-konva';
import useImage from 'use-image';
const MyImage = ({ url }) => {
// useImage 钩子自动处理跨域
const [image] = useImage(url, 'Anonymous');
return (
<Image
x={50}
y={50}
image={image}
/>
);
}
const App = () => {
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<MyImage url="your-image-url" />
</Layer>
</Stage>
);
};
<template>
<v-stage :config="stageSize">
<v-layer>
<v-image
v-if="image"
:config="{
x: 50,
y: 50,
image: image
}"
/>
</v-layer>
</v-stage>
</template>
<script setup>
import { useImage } from 'vue-konva';
const stageSize = {
width: window.innerWidth,
height: window.innerHeight
};
// useImage 钩子自动处理跨域
const [image] = useImage('your-image-url', 'Anonymous');
</script>
如果它不起作用怎么办?
在所有情况下,它可能仍然不起作用。如果不起作用,则必须以不同的方式配置你的服务器(这超出了 Konva 的范围),或者你可以尝试将图像存储在其他支持 CORS 请求的地方。