I need to render font awesome image using canvas drawImage(). The drawImage accept image argument:
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage#image An element to draw into the context. The specification permits any canvas image source, specifically, an HTMLImageElement, an SVGImageElement, an HTMLVideoElement, an HTMLCanvasElement, an ImageBitmap, an OffscreenCanvas, or a VideoFrame.
I found the svg file from Font Awesome repository. For example: https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/svgs/solid/calendar.svg
So here is my working code:
const context = document.getElementById("myCanvas").getContext('2d');
const image = new Image();
image.src = `https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/svgs/solid/calendar.svg`;
image.onload = function(){
context.drawImage(image, 0, 0, 100, 100);
};
<canvas id="myCanvas" width="200" height="100"
style="border:1px solid #000000;">
But the svg file has a black color with white background. I want to change the color and the background font awesome icon before rendering. How can I do that? Here is my current attempt. Currently it has this error: DOMException: The source image could not be decoded. and I don't think my current approach will work anyway...
const context = document.getElementById("myCanvas").getContext('2d');
modifyAndDraw(
`https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/svgs/solid/calendar.svg`,
context
);
async function modifyAndDraw(iconUrl, ctx) {
try {
const svgText = await fetchData(iconUrl);
const modifiedSvgText = modifySvgContent(svgText, '#ff0000', '#00ff00');
const imageBitmap = await createImageBitmap(
new Blob([modifiedSvgText], { type: 'image/svg+xml;charset=utf-8' })
);
ctx.drawImage(imageBitmap, 0, 0, 100, 100);
} catch (error) {
console.error('Error:', error);
}
};
async function fetchData(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch data from ${url}`);
}
return response.text();
};
async function modifySvgContent(svgText, fillColor, backgroundColor) {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(svgText, 'image/svg+xml');
const svgElement = xmlDoc.documentElement;
// Change fill color
svgElement.querySelectorAll('[fill]').forEach((element) => {
element.setAttribute('fill', fillColor);
});
// Add background color
svgElement.setAttribute('style', `background-color: ${backgroundColor}`);
return new XMLSerializer().serializeToString(svgElement);
};
<canvas id="myCanvas" width="200" height="100"
style="border:1px solid #000000;">
Using
createImageBitmapdirectly with a Blob containing the modified SVG data should work, but looks like there is some issue with decoding the SVG data when using this method.You can try using the
Imageobject with a data URL to decode and render the SVG data correctly.