instructions
Canvas globalCompositeOperation attribute was first known when a scratch-card effect needed to be implemented. At that time, the effect of scratch-card was found online and the task was finished as soon as possible. This time, I will learn again, hoping to deepen my understanding.
Let’s take a look at the Canvas’s globalCompositeOperation property to see what it does.
define
The globalCompositeOperation property sets or returns how a source (new) image is drawn to the target (existing) image. Source image = the drawing you intend to place on the canvas. Target image = a drawing that you have placed on the canvas.
This attribute is used to set up to create a new shape in the application of synthetic operation type, such as on a blue rectangle to draw a red circle, is displayed in red, or blue in the display, overlapping part of the display or not, don’t overlap how, according to some conditions, such as in the face of these situations, This is where the globalCompositeOperation property comes into play. In the case of default values, both are displayed, and the newly drawn graph overwrites the original graph.
usage
Default value: the source – over grammar: context. GlobalCompositeOperation = “source – in”;
The blue rectangle in the table is the target image and the red circle is the source image.
Attribute values | describe | The effect |
---|---|---|
source-over | The default. Displays the source image on the target image. | |
source-atop | Displays the source image at the top of the target image. Parts of the source image that lie outside the target image are not visible. | |
source-in | Displays the source image in the target image. Only part of the source image within the target image is displayed, and the target image is transparent. | |
source-out | Displays the source image outside the target image. Only parts of the source image other than the target image are displayed, and the target image is transparent. | |
destination-over | Displays the target image above the source image. | |
destination-atop | Displays the target image at the top of the source image. Portions of the target image other than the source image are not displayed. | |
destination-in | Displays the target image in the source image. Only parts of the target image within the source image are displayed, and the source image is transparent. | |
destination-out | Displays the target image outside the source image. Only parts of the target image outside the source image are displayed, and the source image is transparent. | |
lighter | Display source image + target image. | |
copy | Displays the source image. Ignore the target image. | |
xor | Combine source and target images using xor operations. |
All right, let’s get a picture of the effect of water droplet diffusion
Implementation approach
First draw a black and white picture on a canvas, and then set the background to a colored picture. When the mouse clicks, set the canvas globalCompositeOperation property to destination-out. According to the coordinates of the mouse in the canvas, The black and white images are erased by increasing the size of an irregular shape to slowly reveal a colorful background.
So we need three images
Black and white picture
Color picture
Pictures of irregular shapes
code
<html>
<head>
<meta charset="UTF-8">
<style>
canvas {
/* Set the mouse cursor to an image, with 16 and 22 representing the X and Y coordinates of the hotspot */
/* https://developer.mozilla.org/zh-CN/docs/Web/CSS/cursor/url */
cursor: url('https://www.kkkk1000.com/images/globalCompositeOperation/mouse.png') 16 22, auto;
}
</style>
</head>
<body>
<canvas id="canvas" width="400px" height="250px"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
// Save an array of image paths
var urlArr = ["https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/5/29/1725e93d0b71ce7f~tplv-t2oaga2asx-image.image"."https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/5/29/1725e93d1b78677c~tplv-t2oaga2asx-image.image"];
// imgArr stores an array of loaded images. ImgArr stores real images
// loadImg is used to load all images in urlArr
// Return an array of all images
var imgArr = loadImg(urlArr);
// flag is used to limit click events. An image can only be used once
var flag = false;
function loadImg(urlArr) {
var index = 0;
var res = [];
// Pass the load function an image path each time to load the image
load(urlArr[index]);
function load(url) {
// If index equals urlarr.length,
// End the load function when all images are loaded
if (index == urlArr.length) {
// Load the entire image and call init
init();
return;
}
var img = new Image();
img.src = url;
// The next image is loaded regardless of whether the current image is loaded successfully or not
img.onload = next;
img.onerror = function () {
console.log(res[index] + "Load failed");
next();
}
// next is used to load the next image
function next() {
// Save the loaded image in res
res[index] = img;
load(urlArr[++index])
}
}
// Finally returns an array that holds all the real images
return res;
}
function init() {
// Draw a black and white image on the canvas first, then set the background to a color image
// Avoid displaying color images first and then black and white images
context.globalCompositeOperation = "source-over";
context.drawImage(imgArr[0].0.0.400.250);
canvas.style.background = 'url(https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/5/29/1725e93d199be90d~tplv-t2oaga2asx-image.ima ge)';
canvas.style.backgroundSize = "100% 100%";
// When flag is true, mouse click will have the effect of droplet diffusion
flag = true;
// Canvas binding click event, click on the droplet spread effect
canvas.onclick = diffusion;
}
// width indicates the size of an irregularly shaped image
var width = 0;
// speed Indicates the speed of diffusion effect
var speed = 8;
// The diffusion function produces the effect according to the mouse coordinates
function diffusion (e) {
if (flag) {
flag = false;
context.globalCompositeOperation = "destination-out";
window.requestAnimationFrame(draw);
// Draw the diffusion effect according to the mouse coordinates
function draw() {
// It doesn't have to be 1800, but it does have to be a large enough number to spread out across the background
if (width > 1800) {
flag = true;
return;
}
width += speed;
// Get the coordinates of the mouse relative to canvas
var x = e.layerX;
var y = e.layerY;
// Draw pictures with irregular shapes, gradually increasing the image size
context.drawImage(imgArr[1], x - (width / 2), y - (width / 2), width, width);
window.requestAnimationFrame(draw); }}}</script>
</body>
</html>
Copy the code
Let’s go ahead and implement a scratch card effect
rendering
The idea of realizing the effect of scratch card:
First draw a layer of gray on a canvas, then set the canvas background, set the canvas globalCompositeOperation property value to destination-out, click and move, erase the gray according to the coordinates of the moving point, when erase part, Then it automatically erases all the gray to reveal the background.
The scratchcard effect is almost identical to the droplet diffusion effect in the beginning, but the droplet diffusion effect uses an irregularly shaped image to remove black and white images, while the scratchcard effect uses a thick line to remove gray. The main difference is that the scratchcard effect ends up automatically erasing all the gray, and there are two ways to do it.
The first method uses canvas getImageData method to obtain pixel information on canvas. The data property of the object returned by this method is a one-dimensional array containing RGBA order data, which is represented by integers from 0 to 255 (inclusive). See canvas pixel manipulation for details. This method is used to determine how many pixels have been erased, that is, a variable is used to record how many pixels RGBA value is 0, and when the variable value exceeds a certain value, all grays are cleared.
The code is here.
The second is to see how much the mouse moves directly. When the mouse moves, there will be a variable for self-increasing operation. When the variable exceeds a certain value, it will erase all the gray.
The code is here.
Note: The first way to use getImageData has cross-domain problems, but because this effect does not draw a picture on the canvas, it sets the background of the canvas to a picture, so this does not affect, but if other pictures are drawn on the canvas, You might need to deal with cross-domain problems. With getImageData, pixel information on canvas can be obtained, and the time of erasing all gray can be determined according to the gray area on the scratch card, which is more flexible.
In the second way, although there is no cross-domain problem, it cannot well control the timing of the final erasure of all gray according to the gray area on the scratch card.
conclusion
The effect in this article mainly uses the globalCompositeOperation attribute as destination-out, and other values can also be used to create various effects. You can also use your imagination to try other values and maybe make new discoveries.