How does the Image type work? Is it any different from just using a URL for the image?
What happens when the URL changes or gets taken down? You lose the image without knowing.
Also, by storing the image in the db, you can refer to it in many places much more easily than a URL. Lastly, you can send it in a workflow, a URL wouldn’t work as well.
Good points. But I was wondering if, internally, Bubble is just treating the Image type as a URL, pointing to its own storage. Or is it actually some kind of blob like you’d find in other languages?
You’re right, it’s still an AWS URL that Bubble converts.
OK, so if I was to pass an Image field to a plugin via it’s parameters it could be read as a simple url in text?
If only it were that simple! The photo parameter resolves as a text URL just fine, but now we hit the dreaded CORS:
> Access to image at 'https://s3.amazonaws.com/appforest_uf/f1550113848736x494222869982514400/picture%20wall.jpg' from origin 'https://imagematter-test-4.bubbleapps.io' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
> s3.amazonaws.com/appforest_uf/f1550113848736x494222869982514400/picture%20wall.jpg:1 Failed to load resource: net::ERR_FAILED
Anybody got any suggestions how to use the Image Type in a plugin and avoid the CORS pothole?
Are you only looking to send a URL? Just curious why you don’t send the image as a file.
The user can upload an image and that works fine as an Image. But the app is about displaying those saved images. The way they are displayed is via a plugin that I wrote that does several manipulations to the images (size, shape, add borders, montage, detect common color pallette, etc.). Many things Bubble can’t natively do. But I have to be able to get the image into the plugin. URL is easy regardless of where the image is stored.
It all works currently with URL’s as text. My original question was to find out what advantage there is to using the Image Type. But since converting the Image to a URL creates a CORS issue it seems like I should just keep referencing the user photos as text/URL.
Is it solved for you? Because I have a plugin that works with images, I just don’t know if it would be useful to you.
It’s like this:
// because bubble doesn't passes the protocol, only the link, so we append the protocol ourselves
let fixedImageUrl = `https:${properties.image_link}`;
// this function grabs an image URL (string) and outputs its dataURL (very long string)
function imgURLToDataURL(url, options = {}) {
return new Promise((resolve, reject) => {
img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = () => {
let canvas = document.createElement('CANVAS'),
ctx = canvas.getContext('2d'),
dataURL;
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img, 0, 0);
dataURL = canvas.toDataURL(options.outputFormat, options.quality);
resolve(dataURL);
canvas = null;
};
img.src = url;
});
}
Then
imgURLToDataURL(fixedImageUrl)
.then(function(dataURL){
//callback
});
There’s a bit more to it, in the callback I solve another promise so I can pass the DataURL string to other async code through .then
.
Hey Vini, that’s a bit complicated for me.
I think you are taking the url and turning it into a local ‘file’ in the client and changing the cross origin label at the same time? That’s an interesting idea. It may not work for me as I have a lot of quite large images on each page. It could cause problems. But if I can’t find another solution I will give it a try.
Thanks!
I’m going to move this discussion to another for generic thread on CORS specifically: CORS Issues in Bubble.
You have some options here but I will leave the options requiring Bubble to alter their service for another thread.
The methods I use change a lot depending on the site or circumstance but perhaps one of the easiest ways when you have the luxury of accessing the element before run time is to use HTML element’s with a image tag.
<img crossOrigin="anonymous" src="//s3.amazonaws.com/appforest_uf/f1535229274297x436912684701383100/premier_code_full.png">
You will have the benefit of complete ease of element’s code customization with this method at the cost of some styling may come from your own attributes rather than the Bubble composer.
Of course sometimes we like the easy way and we don’t want to use HTML for every image, for this scenario you can use a function as vini points out above, The concept of this method is much the same except I prefer not to add a canvas transfer of converted image data this can lead to some issues in broader cases but more to the point its not necessary to achieve our goal. Here is a rough idea of a per image basis.
<script>
function fixCorrs(id){
var a = $('#' + id).attr('src');
var e = document.createElement('img');
e.crossOrigin = 'anonymous';
e.width = $(p).width();
e.height = $(p).height();
$(p).parent().append(e);
e.src = decodeURIComponent(a);
$(p).remove();
}
</script>
By placing the above code in your pages header, you will be free to use toolbox to run
fixCorrs("SomeImageIdHere");
for any images refusing to play ball.
There is the other scenario that involves many images, a lack of desire or know how using scripts & functions. In this case I achieve my result in much the same way as the second method with the slight exception of some extra code that in a nut shell says go to town.
<script>
(function(){
$.each($('img'), function(o, p) {
var u = '//dhtiece9044ep.cloudfront.net/';
if ($(p).attr('src') != u + 'static/img/transparent.png' && $(p).attr('src') != u + 'f1531434913430x146164048230275520/Logo-no-clearspace%20Dark.svg') {
var a = $(p).attr('src');
var e = document.createElement('img');
e.crossOrigin = 'anonymous';
e.width = $(p).width();
e.height = $(p).height();
$(p).parent().append(e);
e.src = decodeURIComponent(a);
$(p).remove();
}
});
})();
</script>
The above script basically leaves alone bubbles famous transparent fallback images & the tripwire Bubble image in the Bubble banner while performing the above fix on all other images. This one can be triggered when needed but for best results just place it in the header and run it only if new images are on the scene. You could also place a switch in the code to avoid images with the corrs fix already to optimize the whole task a lot.
Remember if your using toolbox always remove the
<script></script>
tags or your images will be one of many console errors
The real preference here though would be Bubble adding a checkbox to add the crossOrigin attribute in the first place when using an image element but thats just my 6 cents.
Wow, PWC, thank you! I got excited by your first suggestions (didn’t know you could change origin as easily as that). But my situation doesn’t allow me to create simple tags. In my plugin I’m using a lib called Croppie to size and crop the user images. The image URL is passed like this:
$(instance.data.newDiv2).croppie({
viewport: { width: (instance.canvas.width()*instance.data.pic_mat_ratio), height: (instance.canvas.height()*instance.data.pic_mat_ratio) },
boundary: { width: (instance.canvas.width()*instance.data.pic_mat_ratio), height: (instance.canvas.height()*instance.data.pic_mat_ratio) },
showZoomer: false,
enableResize: false,
enableOrientation: true,
enforceBoundary: true,
url: properties.image_url,
update: function (data) { //when Croppie updates
}
}
Without hacking Croppie’s code I am not sure any of your solutions would work, would they?