Building an Image Generator for the Number 1 Track on Spotify ūüĆč
I’ve created plenty of image generators in the past and these projects typically start by reverse engineering the artwork into drawing instructions that I can use alongside HTML5 canvas to construct new images. The area that is truly dynamic on our meme is the names written on masking tape. If we consider each piece of tape individually, we’ll want to understand it’s position, rotation, text alignment, and width. I then add these properties to an array I can reference later. Here’s an example of one friend:
[ { original: "Ozuna", name: "", rotation: -90, top: -300, left: 0, align: "left", width: 550, height: 145 }]
With my drawing array prepared, it’s time to create the tape collage. Note, that this still doesn’t include the volcano background image. I am simply turning the four name fields into the tape collage using my drawing instructions. The first thing we’ll want to do is create an offline canvas that will hold our tape collage.
let tapeCanvas = document.createElement('canvas')
tapeCanvas.height = 1080tapeCanvas.width = 1080
let tapeContext = tapeCanvas.getContext('2d')
We will then loop through each of the friends and create yet another offline canvas for each. This time the canvas will be sized to that of a piece of tape and we’ll add both a tape texture and the friend’s name. Finally, we’ll want to add each individual tape canvas onto the tape collage using the position and rotation properties we set up beforehand. Here’s the whole code block:
this.friends.forEach((friend, index) => { let canvas = document.createElement('canvas')
canvas.height = friend.height canvas.width = friend.width
let context = canvas.getContext('2d')
context.drawImage(tapeImage, 0, 0, canvas.width, canvas.height)
context.fillStyle = '#003A94' context.font = "130px 'Brush'" context.textAlign = friend.align context.textBaseline = 'middle'
context.fillText( friend.name.toUpperCase(), canvas.width * friend.start, canvas.height / 2 )
tapeContext.drawImage( canvas, (tapeCanvas.width / 2) - (canvas.width / 2), (tapeCanvas.height / 2) - (canvas.height / 2) )
tapeContext.setTransform(1, 0, 0, 1, 0, 0)})
Once I have created my tape collage, I will simply draw it onto each of my various background sizes. I’ve made this easy for myself by making sure each composition accepts a square tape collage aligned to the center of the image. For example, here’s what it takes to create the portrait image.
context.drawImage(backgroundImage, 0, 0, 720, 1280)context.drawImage(tapeCanvas, 0, 280, 720, 720)
Easy stuff. You spend a bit more time on the frontend reverse engineering the image and defining each of those drawing properties, but the outcome of that work is things falling perfectly into place.