Notice
You need to be able to apply what I did fundamentally even though I am using the tag tutorial
. I added the tag because I think you can still reduce the time for Trial and Error
in case you get a similar situation.
Background
One of the clients at work
wanted to show an Avatar when sharing a page via Facebook. So I had to enable their Web Application to generate a URL forog:image
and its related Open Graph Tags.The problem was that there is no actual PNG Image stored within the App as it shows the Avatar with the combination of
SVG Image related tags
andCSS
. So I had to come up with a way to generate the PNG Version of the Avatar before amending the logic for Open Graph Tags.
I ended up spending hours to clear out the uncertainties with my-coworkers and then made this happen as follows:
- Capture final Avatar Image at Frontend ( The web browser )
- Send the image data to the server
- Make the server generate PNG Image with the image data
- Store the PNG Image in the way the Web Application can provide the URL for it
- And then generate Open Graph Tags accordingly
Troublesome.
I could have tried to render the Avatar at server side by mucking around existing Avatar Component and then convert it to PNG Image, but I didn't really spend time to see if that way works out because the Component has a lot of mumbo jumbo with jQuery aka the code made by someone else or me in the past
. Besides, that way may break existing logic. So I chose the path with spaghetti code but it works
as usual.
Solution
At first, I was trying to make this happen with Node.js Packages letting me convert SVG Image to PNG Image, and then noticed that some bits of Avatar are drawn with CSS and therefore I don’t get the same appearance with those Packages (because you cannot use CSS as parameter, well, maybe you can, I did not check that, and I don’t want to go back there and then re-factor the further code in case that worked). Anyway, I ended up using html2canvas to make this happen.
Code Example
This is not the exact code for the Web Application, but if you are an experienced web developer, you should be able to copy the important bits and avoid browsing around Stack Overflow pages etc.
Frontend
// This part gets thrown to Babel prior to being loaded by web browsers
// so that this ECMA Script works when the browser actually executes it
onAfterYourComponentRenderedAvatar() {
const selector = '#container-for-avatar';
const element = jQuery(selector);
// Enable to revert the original size
const width = element.width();
const height = element.height();
// Fix the size to make "html2canvas()" capture the Avatar properly
// You may need to muck around more here to make that happen
element.width(240).height(240);
// Capture the Avatar made by the combination of SVG and CSS
// Lucky this worked in my case
html2canvas(
document.querySelector(selector),
{
// Another part of making "html2canvas()" capture the Avatar properly
// Skipping to think logically and/or amend other existing code
scrollX : -9,
// Make the background transparent, as the Avatar has the shape of circle in my case
backgroundColor : null,
},
)
.then((canvas) => {
// Revert the Avatar Element to have the original size
element.width(width).height(height);
// Debug to see how it went
// document.querySelector('#example-container').appendChild(canvas);
// Send the image data to the server
const opts = {
method : 'POST',
headers : {
Accept : 'application/json',
'Content-Type' : 'application/json',
},
// Not sure if I need this bit
redirect : 'follow',
// I guess this is safe to put
credentials : 'same-origin',
// Main bit, you can buy me a cup of coffee forever
body : JSON.stringify({
avatar : canvas.toDataURL('image/png'),
}),
};
fetch(`/example/${id}/avatar/png`, opts);
});
}
Backend
/**
* Save PNG Version of Avatar
* in case App uses ExpressJS etc
*/
app.post(
'/example/:id/avatar/png',
(req, res) => {
if (!req.body.avatar) {
return; // or whatever
}
// Mumbo Jumbo Code prior to saving the PNG Version of Avatar here
// Extract the image data from the request data
const dataaaaaaaa = req.body.avatar.split(',')[1];
const bufferrrrrr = Buffer.from(dataaaaaaaa, 'base64');
// Save the image with "bufferrrrrr" or whatever you have to do
// to enable your App to let us refer the image via URL so that Facebook can
// I do not name variables like "bufferrrrrr" in case you wondered
},
);
/**
* When showing the page having "og:image" etc
*/
// Just generate the META Tags with the URL for the PNG Version of Avatar
References
I don’t remember because it was almost midnight when it started working. And that is the intention of this post, helping others by sharing my experience.
Top comments (0)