- HTML5 Canvas: How To Add Text To An Image (10 Working Demos)
- Step 1: Loading An Image (A Few Different Ways, Based On Your Needs)
- Option 1: Loading An Image From A URL & Setting The Width & Height Of The Canvas To Match The Image
- The “drawImage” function..
- Option 2: Loading An Image From An IMG Tag & Setting The Width & Height Of The Canvas To Match The Image
- Option 3: Loading An Image Where The Canvas Has A Fixed Size & The Image Is Larger & We FIT The Image Inside The Canvas Without Cropping
- Option 4: Loading An Image That Is Larger Than The Canvas, And Filling The Canvas With The Image (some cropping of the image will occur)
- Step 2: Writing Text On Top Of An Image (A Few Different Ways, Based On Your Needs)
- Adding Text To An Image Like A Watermark
- Writing Text On Top Of An Image With Word Wrap
- Writing Text On Top Of An Image With Word Wrap (Center Align)
- Writing Text On Top Of An Image With A Custom Font (Loaded Via CSS)
- But, there is an issue to look out for…
- Writing Text On Top Of An Image With A Custom Font (Loaded Via JS)
- Bonus Tip: Add A Dark Overly To Make The Text More Readable When Writing Text Over The Image
HTML5 Canvas: How To Add Text To An Image (10 Working Demos)
Step 1: Loading An Image (A Few Different Ways, Based On Your Needs)
Option 1: Loading An Image From A URL & Setting The Width & Height Of The Canvas To Match The Image
The plan for us to do this is as follows:
- Create a new “Image” via JavaScript (docs from MDN) ( let img = new Image ( ) ; )
- For that Image, write a function to say what happens after the loading of the image is completed. (image.onload = ..)
- Once the image is loaded, we get the width and height of the image, so we can use that to set the width and height of the canvas
- Finally, we draw the image on top of the canvas using the “drawImage” function. (docs from MDN)
let loadImageOnCanvasAndResizeCanvasToFitImage = (canvas, imageUrl) => < // Get the 2D Context from the canvas let ctx = canvas.getContext("2d"); // Create a new Image let img = new Image(); // Setting up a function with the code to run after the image is loaded img.onload = () =>< // Once the image is loaded, we will get the width & height of the image let loadedImageWidth = img.width; let loadedImageHeight = img.height; // Set the canvas to the same size as the image. canvas.width = loadedImageWidth; canvas.height = loadedImageHeight; // Draw the image on to the canvas. ctx.drawImage(img, 0, 0); >; // Now that we have set up the image "onload" handeler, we can assign // an image URL to the image. img.src = imageUrl; >;
An here is the live working example..
The “drawImage” function..
As you can see above, the “drawImage” function is used to draw the text on top of an image.
There are a few different ways you could use the function like:
- drawImage(image, dx, dy)
- drawImage(image, dx, dy, dWidth, dHeight)
- drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
Now, in the above code, we have use the first method. But, in other situations, we will have to use the other function signatures.
What the different parameters mean..
As you can see you have a lot of control. Using the parameters, you can take even a small part of the image and place it anywhere on the canvas.
You probably guessed it, but the “s” prefix means “source”. Also the “d” prefix means “destination”.
So, the different parameters mean the following:
- dx: When placing the image on the canvas (in its destination) what should be the x coordinate of the top right corner.
- dy: When placing the image on the canvas (in its destination) what should be the y coordinate of the top right corner.
- dWidth & dHeight: What should be the width and height of the image on the canvas.
- sWidth & sHeight in combination with sx, & sy: What should be the “window” (in terms of width and height, starting at sx and sy) we crop out of the source image to place it on the canvas.
The method signature we have used above is:
drawImage(image, dx, dy)
In this form, we are saying: “I want the whole image. And place it at the dx, dy coordinates on my canvas” (As you can see from the the image above, the 0,0 point is the top left corner.)
Option 2: Loading An Image From An IMG Tag & Setting The Width & Height Of The Canvas To Match The Image
So, here we will assume that you already have an IMG tag on your page with the image. This is not likely, because then you would have 2 places on your page with the same image. But still, lets make that assumption.
function loadCanvasWithImageBasedOnImagTag(imageID, canvasID) < // get the image let theImage = document.getElementById(imageID); // get the canvas let theCanvas = document.getElementById(canvasID); // get the canvas 2D context let ctx = theCanvas.getContext("2d"); // Create a function to run after the image is loaded let runAfterImageIsLoaded = () => < // set the canvas width and height to the image theCanvas.width = theImage.width; theCanvas.height = theImage.height; // Draw the image on the canvas ctx.drawImage(theImage, 0, 0); >// If we can access the image width, then the image must already be loaded! if ( theImage.width ) < runAfterImageIsLoaded(); >// Just incase the image is not loaded, then we will set up the function to be run // as soon as the image gets loaded.. theImage.onload = runAfterImageIsLoaded; >
Option 3: Loading An Image Where The Canvas Has A Fixed Size & The Image Is Larger & We FIT The Image Inside The Canvas Without Cropping
In this situation, the image has a width or height that is bigger than the canvas. So, we have scale the image down and centre it and place it in the middle of the canvas.
- Our image of Mona from Wikipedia is 402×599
- We want to stick it into a canvas of: 400×400
So, the end result will look like this…
The plan to achieve this is as follows:
- Figure out how much we need to “scale down” the image.
- Reduce the width and height of the image by that “scale factor”
- Place the image in the centre of the canvas
The code to achieve all this is as follows:
And here is the working demo…
Option 4: Loading An Image That Is Larger Than The Canvas, And Filling The Canvas With The Image (some cropping of the image will occur)
First let us look at how the result looks when an image of size: 402×599 is made to “fill up” a canvas of size: 400×400
The code the achieve this is almost exactly the same as before. The only difference is when we try to calculate the “scale” we look for the max ratio instead of the min. (see line 9 below)
// Setting up a function with the code to run after the image is loaded img.onload = () => < // Once the image is loaded, we will get the width & height of the image let loadedImageWidth = img.width; let loadedImageHeight = img.height; // get the scale // it is the min of the 2 ratios let scaleFactor = Math.max( canvas.width/img.width, canvas.height/img.height); // Finding the new width and height based on the scale factor let newWidth = img.width * scaleFactor; let newHeight = img.height * scaleFactor; // get the top left position of the image // in order to center the image within the canvas let x = ( canvas.width/2 ) - ( newWidth/2 ); let y = ( canvas.height/2 ) - ( newHeight/2 ); // When drawing the image, we have to scale down the image // width and height in order to fit within the canvas ctx.drawImage(img, x, y, newWidth, newHeight); >;
And here is the code in action..
Step 2: Writing Text On Top Of An Image (A Few Different Ways, Based On Your Needs)
Now that the image is loaded, we can start to write text on top of it.
Below we will look at some code snippets to handle various text writing needs.
Adding Text To An Image Like A Watermark
Here is a function that can be used..
let loadImageOnCanvasAndThenWriteText = (canvas, imageUrl, textToWrite, textStyleOptions, xCordOfText, yCordOfText) => < // Get the 2D Context from the canvas let ctx = canvas.getContext("2d"); // Create a new Image let img = new Image(); // Setting up a function with the code to run after the image is loaded img.onload = () =>< // Once the image is loaded, we will get the width & height of the image let loadedImageWidth = img.width; let loadedImageHeight = img.height; // Set the canvas to the same size as the image. canvas.width = loadedImageWidth; canvas.height = loadedImageHeight; // Draw the image on to the canvas. ctx.drawImage(img, 0, 0); // Set all the properties of the text based on the input params ctx.font = `$px $`; ctx.fillStyle = textStyleOptions.textColor; ctx.textAlign = textStyleOptions.textAlign; // Setting this so that the postion of the text can be set // based on the x and y cord from the top right corner ctx.textBaseline = "top"; // Finanlly addeing the text to the image ctx.fillText(textToWrite, xCordOfText, yCordOfText); >; // Now that we have set up the image "onload" handeler, we can assign // an image URL to the image. img.src = imageUrl; >;
As you can see above, once the image is loaded, we start to draw the text on the image.
The code to call the function looks like this..
// Setting up the canvas let theCanvas = document.getElementById("myCanvas"); // Some image URL.. let imageUrl = "https://livefiredev.com/wp-content/uploads/2022/08/mona-lisa.jpeg"; let textStyleOptions = < fontSize: 30, fontFamily: "Arial", textColor: "rgba(255, 255, 255, 0.4)", textAlign: "left" >; let textToWrite = "© daVinci - Year 1503"; let xCordOfText = 10; let yCordOfText = 10; // Load image on the canvas & then write text loadImageOnCanvasAndThenWriteText( theCanvas, imageUrl, textToWrite, textStyleOptions, xCordOfText, yCordOfText );
Finally here is a working demo..
Writing Text On Top Of An Image With Word Wrap
HTML5 Canvas does not have any built in “line break” and “word wrap” system. However, we can use the “measureText“ function to figure out how much space the text to be drawn will take.
Below is a function you can use for this purpose..
function getLines(ctx, text, maxWidth) < var words = text.split(" "); var lines = []; var currentLine = words[0]; for (var i = 1; i < words.length; i++) < var word = words[i]; var width = ctx.measureText(currentLine + " " + word).width; if (width < maxWidth) < currentLine += " " + word; >else < lines.push(currentLine); currentLine = word; >> lines.push(currentLine); return lines; >
I have modified the code in the above example to use this function. The new function is as follows:
let loadImageOnCanvasAndThenWriteText = ( canvas, imageUrl, textToWrite, textStyleOptions, xCordOfText, yCordOfText, textBoundingBoxWidth ) => < // Get the 2D Context from the canvas let ctx = canvas.getContext("2d"); // Create a new Image let img = new Image(); // Setting up a function with the code to run after the image is loaded img.onload = () =>< // Once the image is loaded, we will get the width & height of the image let loadedImageWidth = img.width; let loadedImageHeight = img.height; // Set the canvas to the same size as the image. canvas.width = loadedImageWidth; canvas.height = loadedImageHeight; // Draw the image on to the canvas. ctx.drawImage(img, 0, 0); // Set all the properties of the text based on the input params ctx.font = `$px $`; ctx.fillStyle = textStyleOptions.textColor; ctx.textAlign = textStyleOptions.textAlign; // Setting this so that the postion of the text can be set // based on the x and y cord from the top right corner ctx.textBaseline = "top"; // Get lines array let arrayOfLines = getLines(ctx, textToWrite, textBoundingBoxWidth); // Set line height as a little bit bigger than the font size let lineheight = textStyleOptions.fontSize + 10; // Loop over each of the lines and write it over the canvas for (let i = 0; i < arrayOfLines.length; i++) < ctx.fillText(arrayOfLines[i], xCordOfText, yCordOfText + ( i * lineheight ) ); >>; // Now that we have set up the image "onload" handeler, we can assign // an image URL to the image. img.src = imageUrl; >;
As you can see, it now takes an extra parameter that defines the “width of the bounding box” around the text.
Lets have a look at all of this in a working demo..
Writing Text On Top Of An Image With Word Wrap (Center Align)
Almost everything here remains the same. The reason I am mentioning this is because you need to look out for some unexpected behaviour.
When you set the “textAlign” property as “center”, the middle of the text becomes the “x” and “y” cord of the text on which everything is based. So, you need to set it appropriately.
Below is a working example..
Writing Text On Top Of An Image With A Custom Font (Loaded Via CSS)
So, when you load fonts via CSS, something like..
In the “head” section of the document, the font can be used to write text on the canvas just like any other text.
But, there is an issue to look out for…
You might find that “sometimes, the font loads and sometimes it does not“. This is happening because the font is loaded after the JS is run.
You can fix this by doing the following….
// Use the JS font load function as below // and run all your canvas setting up code only after // the font is completed loading.. document.fonts.load('100px "Mouse Memoirs"').then(() => < // Setting up the canvas let theCanvas = document.getElementById("myCanvas"); // Some image URL.. let imageUrl = "https://livefiredev.com/wp-content/uploads/2022/08/mona-lisa.jpeg"; let textStyleOptions = < fontSize: 25, fontFamily: "Mouse Memoirs", textColor: "rgba(255, 255, 255, 0.9)", textAlign: "left" >; let textToWrite = "The Mona Lisa is one of the most valuable paintings in the world."; let xCordOfText = 10; let yCordOfText = 10; let textBoundingBoxWidth = 350; // Load image on the canvas & then write text loadImageOnCanvasAndThenWriteText( theCanvas, imageUrl, textToWrite, textStyleOptions, xCordOfText, yCordOfText, textBoundingBoxWidth ); >);
In the previous examples, we were doing all of our canvas code after the document was loaded. As you can see above. Now, we are doing it after the custom fonts are loaded.
Writing Text On Top Of An Image With A Custom Font (Loaded Via JS)
Some times, you might need to load the font you want to use on the canvas “dynamically”. Maybe the use is selecting the font from a drop down. So, lets see how to tackle that situation next.
So, in order to get this done, you can use the Web Font Loader JS libray.
Here is a CDN link for the the same..
Using the library to load Google fonts is quite simple. See the sample code below..
As you can see you just have to specify the font name and weights you want and also what should happen after the fonts are loaded using the “active” key.
Note: This JS library NOT ONLY supports Google Fonts, but many other font sources.
Here is a working example..
Bonus Tip: Add A Dark Overly To Make The Text More Readable When Writing Text Over The Image
Before we write the text, lets just create a slight overlay on top of the image. This will help the text stand out.
All you have to do is create a rectangle and fill the canvas with it after the image is loaded and before you write the text.
// Create a rectangle and fill the canvas with it ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; ctx.fillRect(0, 0, loadedImageWidth, loadedImageHeight);