Copyright Derek O'Reilly, Dundalk Institute of Technology (DkIT), Dundalk, Co. Louth, Ireland.
Composites can be used to blend or mask one or more images and/or one or more text with each other on a canvas.
We use the globalCompositeOperation to blend or mask new content with what is already drawn on a canvas. There are 12 composite operations, as shown below:
Perhaps the most useful alpha composite is the 'source-in composite. It can be used to show part of one image on top of another image.
Example of a source-in alpha composite region (Run Example)
<!DOCTYPE html>
<html>
<head>
<title>Course notes example code</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
img,
canvas
{
width:500px;
height:500px;
border:thin solid black;
}
#loadingMessage
{
position:absolute;
top:100px;
left:100px;
z-index:100;
font-size:50px;
}
</style>
<script>
let canvas = null
let ctx = null
let width = null
let height = null
let originalImage = null
window.onload = onAllAssetsLoaded
document.write("<div id='loadingMessage'>Loading...</div>")
function onAllAssetsLoaded()
{
// hide the webpage loading message
document.getElementById('loadingMessage').style.visibility = "hidden"
originalImage = document.getElementById('originalImage')
canvas = document.getElementById('canvas')
ctx = canvas.getContext('2d')
width = originalImage.clientWidth
height = originalImage.clientHeight
canvas.width = width
canvas.height = height
renderCanvas()
}
function renderCanvas()
{
// 1) define the alpha area
ctx.beginPath()
ctx.fillStyle = "red" // any colour can be used
ctx.fillRect(100, 100, 200, 100)
ctx.closePath()
// 2) select the alpha composite
ctx.globalCompositeOperation = 'source-in'
// 3) draw the original image
// only the part that overlaps the alpha area will be visible
ctx.drawImage(originalImage, 0, 0, width, height)
}
</script>
</head>
<body>
<img id = 'originalImage' src = 'images/dancing.png'>
<canvas id = 'canvas'></canvas>
</body>
</html>
Write code to display a circular (spotlight) image on a full-sized, faded, background image, as shown at this link.
Expand your code so that the user can drag the spotlight around the canvas, as shown at this link.
Expand your code so that the user can drag a magnified spotlight around the canvas, as shown at this link.
List a use for each of the 12 various alpha composites.
Modify the code above so that the user can select any of the 12 alpha composites, as shown at, this link.
Example of a source-in alpha composite image (Run Example)
<!DOCTYPE html> <html> <head> <title>Course notes example code</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> img, canvas { width:500px; height:500px; border:thin solid black; } #loadingMessage { position:absolute; top:100px; left:100px; z-index:100; font-size:50px; } </style> <script> let canvas = null let ctx = null let originalImage = null let width = null let height = null let alphaImage = new Image() alphaImage.src = 'images/four_leaf_clover.png' window.onload = onAllAssetsLoaded document.write("<div id='loadingMessage'>Loading...</div>") function onAllAssetsLoaded() { // hide the webpage loading message document.getElementById('loadingMessage').style.visibility = "hidden" originalImage = document.getElementById('originalImage') canvas = document.getElementById('canvas') ctx = canvas.getContext('2d') width = originalImage.clientWidth height = originalImage.clientHeight canvas.width = width canvas.height = height renderCanvas() } function renderCanvas() { // 1) define the alpha area ctx.drawImage(alphaImage, 100, 50, 200, 200) // 2) select the alpha composite ctx.globalCompositeOperation = 'source-in' // 3) draw the original image // only the part that overlaps the alpha area will be visible ctx.drawImage(originalImage, 0, 0, width, height) } </script> </head> <body> <img id = 'originalImage' src = 'images/dancing.png'> <canvas id = 'canvas'></canvas> </body> </html>
Modify the above code to use a different image.
Example of a source-in alpha composite text (Run Example)
<!DOCTYPE html> <html> <head> <title>Course notes example code</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> img, canvas { width:500px; height:500px; border:thin solid black; } #loadingMessage { position:absolute; top:100px; left:100px; z-index:100; font-size:50px; } </style> <script> let canvas = null let ctx = null let width = null let height = null let originalImage = null window.onload = onAllAssetsLoaded document.write("<div id='loadingMessage'>Loading...</div>") function onAllAssetsLoaded() { // hide the webpage loading message document.getElementById('loadingMessage').style.visibility = "hidden" originalImage = document.getElementById('originalImage') canvas = document.getElementById('canvas') ctx = canvas.getContext('2d') width = originalImage.clientWidth height = originalImage.clientHeight canvas.width = width canvas.height = height renderCanvas() } function renderCanvas() { // 1) define the alpha area ctx.beginPath() ctx.fillStyle = "red" ctx.font = "170px Times Roman" ctx.fillText("DkIT", 25, 200) ctx.closePath() // 2) select the alpha composite ctx.globalCompositeOperation = 'source-in' // 3) draw the original image // only the part that overlaps the alpha area will be visible ctx.drawImage(originalImage, 0, 0, width, height) } </script> </head> <body> <img id = 'originalImage' src = 'images/dancing.png'> <canvas id = 'canvas'></canvas> </body> </html>
Change the text font and position in the code above.
Allow the user to type in the text that will be used as the alpha composite.
Use the global alpha to fade your modified code.
Example of a drop shadow on an image (Run Example)
<!DOCTYPE html> <html> <head> <title>Course notes example code</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> img, canvas { width:500px; height:500px; border:thin solid black; } #loadingMessage { position:absolute; top:100px; left:100px; z-index:100; font-size:50px; } </style> <script> let canvas = null let ctx = null let width = null let height = null let originalImage = null let alphaImage = new Image() alphaImage.src = 'images/four_leaf_clover.png' window.onload = onAllAssetsLoaded document.write("<div id='loadingMessage'>Loading...</div>") function onAllAssetsLoaded() { // hide the webpage loading message document.getElementById('loadingMessage').style.visibility = "hidden" originalImage = document.getElementById('originalImage') canvas = document.getElementById('canvas') ctx = canvas.getContext('2d') width = originalImage.clientWidth height = originalImage.clientHeight canvas.width = width canvas.height = height renderCanvas() } function renderCanvas() { // set up a double-buffer let doubleBuffer = document.createElement('canvas') let doubleBufferCtx = doubleBuffer.getContext('2d') doubleBuffer.width = width doubleBuffer.height = height // define the shadow offset and colour let offset = 10 let shadowColour = '#ff0' // 1) define the alpha area doubleBufferCtx.drawImage(alphaImage, 10, 10, 350, 350) // 2) select the alpha composite doubleBufferCtx.globalCompositeOperation = 'source-in' // 3) draw the original image // only the part that overlaps the alpha area will be visible doubleBufferCtx.beginPath() doubleBufferCtx.fillStyle = shadowColour doubleBufferCtx.fillRect(0, 0, width, height) doubleBufferCtx.closePath() // draw the saved shadow image onto the canvas slightly below and to the right // of where the actual image will be drawn ctx.drawImage(doubleBuffer, 0, 0, width + offset, height + offset) // draw the image slightly above and to the left of the shadow // this is similar to the code above, except now we draw the // original image rather than its shadow doubleBufferCtx.globalCompositeOperation = 'source-over' // 1) define the alpha area doubleBufferCtx.drawImage(alphaImage, 10, 10, 350, 350) // 2) select the alpha operation doubleBufferCtx.globalCompositeOperation = 'source-in' // 3) draw the original image // only the part that overlaps the alpha area will be visible doubleBufferCtx.drawImage(originalImage, 0, 0, width, height) // draw the saved image onto the canvas slightly below and to the right // of where the actual image will be drawn ctx.drawImage(doubleBuffer, 0, 0, width, height) } </script> </head> <body> <img id = 'originalImage' src = 'images/dancing.png'> <canvas id = 'canvas'></canvas> </body> </html>
Change the shadow colour to grey in the example above.
In real shadows, the shadow colour fades out as it moves away from the object. Modify the code above, so that the shadow has ten different shades of grey, as shown at this link.
Replace the overlay image with text in the above example.
Example of a multi-layered image (Run Example)
<!DOCTYPE html> <html> <head> <title>Course notes example code</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> img, canvas { width:500px; height:500px; border:thin solid black; } #loadingMessage { position:absolute; top:100px; left:100px; z-index:100; font-size:50px; } </style> <script> let canvas = null let ctx = null let width = null let height = null let originalImage = null let alphaImage = new Image() alphaImage.src = 'images/overlay.png' let pictureFrame = new Image() pictureFrame.src = 'images/frame.png' window.onload = onAllAssetsLoaded document.write("<div id='loadingMessage'>Loading...</div>") function onAllAssetsLoaded() { // hide the webpage loading message document.getElementById('loadingMessage').style.visibility = "hidden" originalImage = document.getElementById('originalImage') canvas = document.getElementById('canvas') ctx = canvas.getContext('2d') width = originalImage.clientWidth height = originalImage.clientHeight canvas.width = width canvas.height = height renderCanvas() } function renderCanvas() { // 1) define the alpha area ctx.drawImage(alphaImage, 0, 0, width, height) // 2) select the alpha composite ctx.globalCompositeOperation = 'source-in' // 3) draw the original image // only the part that overlaps the alpha area will be visible ctx.drawImage(originalImage, 0, 0, width, height) // draw the picture frame on top of the picture ctx.globalCompositeOperation = 'source-over' ctx.drawImage(pictureFrame, 0, 0, width, height) } </script> </head> <body> <img id = 'originalImage' src = 'images/dancing.png'> <canvas id = 'canvas'></canvas> </body> </html>
Modify the above code to display a different photo frame.
Copyright Derek O' Reilly, Dundalk Institute of Technology (DkIT), Dundalk, Co. Louth, Ireland.