I am storing base64 encoded images, and at the moment I can only create one code (i'm attempting to create two, but it appears the second is being overwritten). I don't get the over-arching concept of canvas drawing, so I believe that is the root of my issue when trying to solve this problem.
current behavior: It stores the same DataUrl in local storage twice. It does log the correct info. the favicon-green is getting stored, just not red
How do I encode multiple base64 images with canvas?
html:
<head>
...
<link id="favicon" rel="icon" src="/assets/favicon-red-16x16.ico.png">
</head>
<body>
...
<!-- hidden images to store -->
<img id="favicon-green" rel="icon" src="/assets/favicon-green-16x16.ico.png" width="16" height="16" />
<img id="favicon-red" rel="icon" src="/assets/favicon-red-16x16.ico.png" width="16" height="16" />
...
</body>
js:
// cache images
function storeImages() {
// my sorry attempt to create two canvas elements for two image encodings
var canvasGreen = document.createElement('canvas');
var canvasRed = document.createElement('canvas');
// painting both images
var ctxGreen = canvasGreen.getContext('2d');
var ctxRed = canvasRed.getContext('2d');
// getting both images from DOM
var favGreen = document.getElementById('favicon-green');
var favRed = document.getElementById('favicon-red');
// checking if images are already stored
var base64Green = localStorage.getItem('greenFavicon');
var base64Red = localStorage.getItem('redFavicon');
console.log('storing...')
if (base64Green == null && window.navigator.onLine || base64Red == null && window.navigator.onLine) {
ctxGreen.drawImage(favGreen, 0, 0);
ctxRed.drawImage(favRed, 0, 0);
// getting images (the DataUrl is currently the same for both)
base64Green = canvasGreen.toDataURL();
base64Red = canvasRed.toDataURL();
localStorage.setItem('greenFavicon', base64Green);
localStorage.setItem('redFavicon', base64Red);
console.log("are they equal : ", base64Green == base64Red); // returns true
}
}
storeImages();
I don't see anything particularly wrong with your code. If the code isn't a direct copy and paste, I would look through it with a fine-tooth come to make sure you don't switch any red and green around.
There shouldn't be any surprising mechanisms when it comes to converting canvases to data URLs.
Here is a quick example of two:
Notice that they are different. However, notice that they also start out very similar, and you have to go quite a ways over to start seeing differences (in my example, character 70). I would double-check that they are actually the same (by comparing them like I did). It could be it just looks the same.
Another thing you might do, which is more of a code style thing, but could also help with accidentally green and red mixups, is make a function to save just one, then call it twice.
Not only does that clean up your code and keep it DRY, but it also helps avoid accidental mix-ups between red and green in your function.
After some comments back and forth, I realized another possibility is you are trying to draw the images to the canvas before the images are loaded. This will cause it to draw blank images, but otherwise act like it is working fine.
You can quickly test this by console logging this:
after setting the image variable. If the value is true, then the image isn't loaded yet (before loading, images will have a width and height of 0). You need to make sure to wait until the image is loaded before trying to save it.
The best way to do this is with an
addEventListener():There is one more catch with this, in that if the image is somehow already loaded by the time that code runs, it'll never trigger. You need to look at the width of the image as well. Here is a function that does this all for you, and returns a
Promiseso you know it's done: