Open wojtekhorembala opened 5 years ago
When i make this gets error from screen
image.addEventListener('load', async () => {
context.drawImage(image, 0, 0, 500, 500);
const imageData = await canvas.toDataURL();
});
I am facing the same issue when I am upgrading react native to 0.59.8. and using react-native-webview 6.1.0
Same issue here on react-native 0.59.10 and react-native-webview 5.8.2
This is a general HTML Canvas issue. Check this discussion: https://stackoverflow.com/questions/25753754/canvas-todataurl-security-error-the-operation-is-insecure. Closing as it is not relevant only for this project.
@PierreCapo Did you find a solution for this?
Not at all, we reprioritized our business requirements 😬
OK thanks anyway. (I didn't notice you are working for BAM, we've been working with them a few years ago 👍)
However I think this issue should be re-opened as I'm facing this error with a local file.
How to fixed ?
Any updates?
I found the solution. Add this.crossOrigin = 'anonymous'
here: https://github.com/iddan/react-native-canvas/blob/master/src/Image.js#L23 and make sure the server from you're requesting images will have CORS enabled.
Unfortunately setting crossOrigin
on initialized Image
constructor doesn't work, so you need to modify the library.
Can confirm solution above works fine.
If anyone wants a working module with a fix for a current issue - feel free to use react-native-canvas-anonymous
.
It it is a fork with just one change (this.crossOrigin = 'anonymous'
) from the suggestion above.
PRs are welcome to fix it here as well.
@iddan To be honest, I've discovered another problem with this.crossOrigin = 'anonymous'
. It prevents image from being loaded, I'm not sure yet why.
I guess because it is insecure to load images from an anonymous origin
I've noticed it depends on the origin, it works on my S3 urls but not cloudfront for example.
Maybe it has to do with CORS headers
I still have another problem, when I use canvas.fillRect and change it to base64 with toDataURL, the question arises anyway
Anyone found a concrete solution for this? Images from links like wikimedia are working with img.crossOrigin = "anonymous"
but for firebase images which I have to work with, the images don't load at all
img.crossOrigin = "anonymous"
may cause the image not to be displayed, so my solution is to convert the image to base64 first before adding it.
This does solve the problem but may reduce performance.
@eashish93 is this still working for you? I added this line to the library but i am getting the error
TypeError: undefined is not a function (near '...this.postMessage...')
and i can't find or figure out an other way to solve this problem.
For me, the issue was happening with a local file, which doesn't make sense as in my opinion, this security feature should only apply to cross-origin content. But I managed to find a workaround.
Before the workaround, I was trying to load the image directly passing the image URI to the image.src
prop. The code was like that:
...
const { imageUri } = route.params // This is the image I'm loading. It's a local image, and it's in this format 'file://...'
function handleCanvas(canvas: Canvas | null) {
if (!canvas) {
return
}
canvas.width = Dimensions.get('screen').width
canvas.height = Dimensions.get('screen').height
const image = new CanvasImage(canvas)
const context = canvas.getContext('2d')
image.src = imageUri
image.addEventListener('load', async () => {
context.drawImage(image, 0, 0, canvas.width, canvas.height)
const pixel = await context.getImageData(0, 0, 1, 1) // This line would throw the error
})
}
...
To make it work I used expo-file-system
to read the image and transform it to a base64 string, and then passed the base64 string to the image.src
prop, like that:
...
const { imageUri } = route.params
async function handleCanvas(canvas: Canvas | null) {
if (!canvas) {
return
}
canvas.width = Dimensions.get('screen').width
canvas.height = Dimensions.get('screen').height
const image = new CanvasImage(canvas)
const context = canvas.getContext('2d')
const base64Image = await FileSystem.readAsStringAsync(imageUri, {
encoding: FileSystem.EncodingType.Base64,
})
image.src = `data:image/png;base64,${base64Image}`
image.addEventListener('load', async () => {
context.drawImage(image, 0, 0, canvas.width, canvas.height)
const pixel = await context.getImageData(0, 0, 1, 1) // No more errors here
})
}
...
Of course, it has the performance downside, but it suits my needs. Also, my problem was with local images, but I think this solution could work for remote images as well (I'm not sure, I haven't tested). I think that a possible approach would be to download the remote image, and then make the same process as I did.
Hope this helps someone!
I didn't have any luck with the crossOrigin
setting, so I ended up using RNFS.downloadFile
and then RNFS.readFile
and made a base64 PNG data URL of the data.
Hi i want little bit optimization my images and i use for this canvas,
Currently i have this code
Can anyone help me? :)