The Sharing: Part 2. Generating Images Using HTML Canvas in JavaScript

Generating Images Using HTML Canvas in JavaScript

The Sharing: Part 2.

This is Part 2 of a series of posts about generating and sharing dynamic images on the web. Check out Part 1 and Part 3.

Check out the companion CodePen while following along with this post.

Part 2: Here’s JPEG!

Introduction to HTML Canvas

You can use HTML <canvas> to generate images via JavaScript. I find it helpful to do as much of the composition beforehand in Figma or a similar design tool before dynamically adding the personalized data using Canvas. Each image will require a slightly different solution depending on the level of dynamic data and the overall composition. In the case of our app, we want to generate both the feed (1:1) and story (9:16) Instagram formats. Since the main element of design is the personalized poster, I’m going to generate and reuse that element, centered, on each of the individual formats. As such, we’ll start with three images: the poster without dynamic name, the story background, and the feed background.

Preloading Assets

Before using HTML Canvas, you’ll want to load both your image assets and any custom typefaces the composition might require.

Here’s a Promise function for loading images.

loadImage(url) {
return new Promise((resolve, revoke) => {
let img = new Image()
img.onload = () => {
resolve(img)
}
img.crossOrigin = 'Anonymous'
img.src = url
})
}

And another you can use for preloading fonts.

loadFont(url) {
return new Promise((resolve, revoke) => {
let font = new FontFace('SF Movie Poster, `url(${url})`)
  font.load()
.then(face => {
document.fonts.add(face)

resolve()
})
.catch(revoke)
})
}

For more info on loading fonts, check out this excellent post.

Using HTML Canvas

Once your images and fonts are loaded, you can begin composing your dynamic image in HTML Canvas. Our image is very simple. We’ll want to first initialize a canvas the size of our poster image, which is 888×1332. Then we’ll draw the poster image onto the canvas. Finally, we’ll write the dynamic name on the poster using our preloaded typeface at the optimal position.

let canvas = document.createElement('canvas')
canvas.height = 1332
canvas.width = 888
let context = canvas.getContext('2d')
context.drawImage(poster, 0, 0)
context.font = "96px SF Movie Poster"
context.textAlign = "center"
context.textBaseline = "top"
context.fillText(name.toUpperCase(), 444, 1028)
return canvas.toDataURL('image/jpeg)

Returning the canvas using toDataURL allows us to display it right from an <img> tag. Here’s a CodePen showing how all of this comes together using Vue.js. Now, all we need to do is use HTML Canvas once again to generate the feed and story images. This is done simply by initiating another canvas for each and drawing both the associated background and the generated poster onto the new canvas at the right position.

For example, here’s how we would generate the feed image.

let canvas = document.createElement('canvas')
canvas.height = 1080
canvas.width = 1080
let context = canvas.getContext('2d')
context.drawImage(feedBackgroundImage, 0, 0)
context.drawImage(posterCanvas, 0, 0, 888, 1332, 244, 96, 592, 888)

I know, I’ve added a lot of numbers to that drawImage method. It’s worth taking a look at the documentation on the method but all I’m doing is telling the method to take the entire poster composition (888×1332,) resize it to 592×888, and place it 244 pixels on the x axis and 96 pixels on the y axis. The story image should be even simpler because we don’t need to resize it. From here, you could use the toDataURL to add the image on an awaiting <img> element.

Downloading Canvas as Image

You could also use the toBlob method alongside the download attribute I mentioned earlier to power a one-click download function. Naturally, there are issues with this method with I mentioned earlier but I have been known to use this technique. Here’s how you might write it.

canvas.toBlob(blob => {
let data = window.URL.createObjectURL(blob)
let link = document.createElement('a')
  link.href = data
link.download = 'feed.jpg'
link.click()
}, 'image/jpeg')

I am using yet another download solution on mobile in the final app but I’ll save that for later. You should now have a pretty good idea of how to generate images in JavaScript on the client. We’ll talk about the server next.

Related Stories


The Sharing: Part 2. Generating Images Using HTML Canvas in JavaScript was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Bits and Pieces - Medium and was authored by Lee Martin

Generating Images Using HTML Canvas in JavaScript

The Sharing: Part 2.

This is Part 2 of a series of posts about generating and sharing dynamic images on the web. Check out Part 1 and Part 3.

Check out the companion CodePen while following along with this post.

Part 2: Here’s JPEG!

Introduction to HTML Canvas

You can use HTML <canvas> to generate images via JavaScript. I find it helpful to do as much of the composition beforehand in Figma or a similar design tool before dynamically adding the personalized data using Canvas. Each image will require a slightly different solution depending on the level of dynamic data and the overall composition. In the case of our app, we want to generate both the feed (1:1) and story (9:16) Instagram formats. Since the main element of design is the personalized poster, I’m going to generate and reuse that element, centered, on each of the individual formats. As such, we’ll start with three images: the poster without dynamic name, the story background, and the feed background.

Preloading Assets

Before using HTML Canvas, you’ll want to load both your image assets and any custom typefaces the composition might require.

Here’s a Promise function for loading images.

loadImage(url) {
return new Promise((resolve, revoke) => {
let img = new Image()
img.onload = () => {
resolve(img)
}
img.crossOrigin = 'Anonymous'
img.src = url
})
}

And another you can use for preloading fonts.

loadFont(url) {
return new Promise((resolve, revoke) => {
let font = new FontFace('SF Movie Poster, `url(${url})`)
  font.load()
.then(face => {
document.fonts.add(face)

resolve()
})
.catch(revoke)
})
}
For more info on loading fonts, check out this excellent post.

Using HTML Canvas

Once your images and fonts are loaded, you can begin composing your dynamic image in HTML Canvas. Our image is very simple. We’ll want to first initialize a canvas the size of our poster image, which is 888x1332. Then we’ll draw the poster image onto the canvas. Finally, we’ll write the dynamic name on the poster using our preloaded typeface at the optimal position.

let canvas = document.createElement('canvas')
canvas.height = 1332
canvas.width = 888
let context = canvas.getContext('2d')
context.drawImage(poster, 0, 0)
context.font = "96px SF Movie Poster"
context.textAlign = "center"
context.textBaseline = "top"
context.fillText(name.toUpperCase(), 444, 1028)
return canvas.toDataURL('image/jpeg)

Returning the canvas using toDataURL allows us to display it right from an <img> tag. Here’s a CodePen showing how all of this comes together using Vue.js. Now, all we need to do is use HTML Canvas once again to generate the feed and story images. This is done simply by initiating another canvas for each and drawing both the associated background and the generated poster onto the new canvas at the right position.

For example, here’s how we would generate the feed image.

let canvas = document.createElement('canvas')
canvas.height = 1080
canvas.width = 1080
let context = canvas.getContext('2d')
context.drawImage(feedBackgroundImage, 0, 0)
context.drawImage(posterCanvas, 0, 0, 888, 1332, 244, 96, 592, 888)

I know, I’ve added a lot of numbers to that drawImage method. It’s worth taking a look at the documentation on the method but all I’m doing is telling the method to take the entire poster composition (888x1332,) resize it to 592x888, and place it 244 pixels on the x axis and 96 pixels on the y axis. The story image should be even simpler because we don’t need to resize it. From here, you could use the toDataURL to add the image on an awaiting <img> element.

Downloading Canvas as Image

You could also use the toBlob method alongside the download attribute I mentioned earlier to power a one-click download function. Naturally, there are issues with this method with I mentioned earlier but I have been known to use this technique. Here’s how you might write it.

canvas.toBlob(blob => {
let data = window.URL.createObjectURL(blob)
let link = document.createElement('a')
  link.href = data
link.download = 'feed.jpg'
link.click()
}, 'image/jpeg')

I am using yet another download solution on mobile in the final app but I’ll save that for later. You should now have a pretty good idea of how to generate images in JavaScript on the client. We’ll talk about the server next.

Related Stories


The Sharing: Part 2. Generating Images Using HTML Canvas in JavaScript was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Bits and Pieces - Medium and was authored by Lee Martin


Print Share Comment Cite Upload Translate Updates
APA

Lee Martin | Sciencx (2021-02-22T15:19:31+00:00) The Sharing: Part 2. Generating Images Using HTML Canvas in JavaScript. Retrieved from https://www.scien.cx/2021/02/22/the-sharing-part-2-generating-images-using-html-canvas-in-javascript/

MLA
" » The Sharing: Part 2. Generating Images Using HTML Canvas in JavaScript." Lee Martin | Sciencx - Monday February 22, 2021, https://www.scien.cx/2021/02/22/the-sharing-part-2-generating-images-using-html-canvas-in-javascript/
HARVARD
Lee Martin | Sciencx Monday February 22, 2021 » The Sharing: Part 2. Generating Images Using HTML Canvas in JavaScript., viewed ,<https://www.scien.cx/2021/02/22/the-sharing-part-2-generating-images-using-html-canvas-in-javascript/>
VANCOUVER
Lee Martin | Sciencx - » The Sharing: Part 2. Generating Images Using HTML Canvas in JavaScript. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/02/22/the-sharing-part-2-generating-images-using-html-canvas-in-javascript/
CHICAGO
" » The Sharing: Part 2. Generating Images Using HTML Canvas in JavaScript." Lee Martin | Sciencx - Accessed . https://www.scien.cx/2021/02/22/the-sharing-part-2-generating-images-using-html-canvas-in-javascript/
IEEE
" » The Sharing: Part 2. Generating Images Using HTML Canvas in JavaScript." Lee Martin | Sciencx [Online]. Available: https://www.scien.cx/2021/02/22/the-sharing-part-2-generating-images-using-html-canvas-in-javascript/. [Accessed: ]
rf:citation
» The Sharing: Part 2. Generating Images Using HTML Canvas in JavaScript | Lee Martin | Sciencx | https://www.scien.cx/2021/02/22/the-sharing-part-2-generating-images-using-html-canvas-in-javascript/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.