I’m using canvas to make a badge. To draw the image I used the code :
JavaScript
x
23
23
1
let image = new Image()
2
image.src = 'imageSource'
3
image.onload = () => {
4
ctx.drawImage(image, xOffset, yOffset, newWidth, newHeight)
5
6
// to color the image at the back (works properly)
7
8
ctx.globalCompositeOperation = 'source-in'
9
ctx.fillStyle = 'someColour'
10
ctx.fillRect(0, 0, this.canvas.width, this.canvas.height)
11
ctx.globalCompositeOperation = 'source-over'
12
13
// icon in the middle
14
15
let iconImage = new Image()
16
iconImage.src = 'iconSource'
17
iconImage.onload = () => {
18
ctx.drawImage(iconImage, xOffset, yOffset, width, height)
19
20
// i need to be able to fill color in this iconImage only
21
}
22
23
The preview is like this.
Now, to color the images, I’ve tried using different blend modes. It works fine when I work it around for the background that is image
. I tried to do it for the iconImage
the same way, but it didn’t work. I want to color the icon in the middle without changing any other thing.
Advertisement
Answer
I was bored in the morning and makes this example for you in this example you can see all the elements in the canvas can be modified.
Note: Because of the CORS issue(Tainted canvases may not be exported), can’t edit the color of the external image here, so import your image using Choose File then change the image color!
JavaScript
1
90
90
1
const canvas = document.querySelector("canvas");
2
const ctx = canvas.getContext("2d")
3
const inputs = document.querySelectorAll("input");
4
const xOffset = 30, yOffset = 10, width = canvas.width-60, height = canvas.height-20;
5
6
var inputValues = {stroke:"#8db5c2",fill:"white",text:"Text",image:"https://i.stack.imgur.com/8eLMW.png",imageColor:"grey"}
7
8
inputs.forEach(input => {
9
input.addEventListener("input", function() {
10
if(this.id === "image") {
11
if (!input.files || !input.files[0]) return;
12
const FR = new FileReader();
13
FR.onloadend = (evt) => {
14
inputValues = {inputValues,[this.id]:FR.result};
15
DrawBadge(inputValues)
16
};
17
FR.readAsDataURL(input.files[0]);
18
} else {
19
inputValues = {inputValues,[this.id]:this.value};
20
DrawBadge(inputValues)
21
}
22
})
23
})
24
25
DrawBadge(inputValues)
26
27
function DrawBadge ({stroke, fill, text, image ,imageColor}) {
28
//Draw Badge
29
ctx.strokeStyle = stroke;
30
ctx.lineWidth = 15;
31
ctx.fillStyle = fill;
32
roundRect(ctx, xOffset, yOffset, width, height, {
33
tl: 1,
34
tr: 1,
35
bl: width/2,
36
br: width/2,
37
});
38
//Draw Text
39
ctx.font = "20px Arial";
40
ctx.textAlign = 'center';
41
ctx.textBaseline = 'middle';
42
ctx.fillStyle = "black";
43
ctx.fillText(text,width/2+xOffset,height*0.8);
44
//Draw Image
45
const firstImage = new Image();
46
const insideWidth = 80, insideHeight = 80;
47
firstImage.src = image;
48
// Because of the CORS issue just show image as it is
49
if(image === "https://i.stack.imgur.com/8eLMW.png") {
50
firstImage.onload = () => {
51
ctx.drawImage(firstImage, (width/2)-(insideWidth/2)+xOffset,height*0.2,insideWidth , insideHeight);
52
}
53
// you should use this function for changing image color
54
} else {
55
firstImage.onload = () => {
56
//Make new canvas for image
57
const imageCtx = document.createElement("canvas").getContext("2d");
58
const insideImage = new Image();
59
imageCtx.canvas.width = insideWidth;
60
imageCtx.canvas.height = insideHeight;
61
imageCtx.save();
62
imageCtx.fillStyle = imageColor;
63
imageCtx.fillRect(0, 0, insideWidth, insideHeight);
64
//Here magic happend
65
imageCtx.globalCompositeOperation = "destination-in";
66
imageCtx.drawImage(firstImage,0,0,insideWidth,insideHeight);
67
//Then export our canvas to png image
68
insideImage.src = imageCtx.canvas.toDataURL("image/png");
69
insideImage.onload = () => {
70
ctx.drawImage(insideImage,(width/2)-(insideWidth/2)+xOffset,height*0.2,insideWidth,insideHeight);
71
}
72
}
73
}
74
}
75
76
function roundRect(ctx, x, y, width, height, radius, fill, stroke){
77
ctx.beginPath();
78
ctx.moveTo(x + radius.tl, y);
79
ctx.lineTo(x + width - radius.tr, y);
80
ctx.quadraticCurveTo(x + width, y, x + width, y + radius.tr);
81
ctx.lineTo(x + width, y + height - radius.br);
82
ctx.quadraticCurveTo(x + width, y + height, x + width - radius.br, y + height);
83
ctx.lineTo(x + radius.bl, y + height);
84
ctx.quadraticCurveTo(x, y + height, x, y + height - radius.bl);
85
ctx.lineTo(x, y + radius.tl);
86
ctx.quadraticCurveTo(x, y, x + radius.tl, y);
87
ctx.closePath();
88
ctx.fill();
89
ctx.stroke();
90
}
JavaScript
1
10
10
1
body {
2
display: flex;
3
}
4
#inputs {
5
display: flex;
6
flex-direction: column;
7
}
8
canvas {
9
border: 1px solid;
10
}
JavaScript
1
12
12
1
<body>
2
<div id="inputs">
3
Stroke Color: <input id="stroke" type="color" value="#8db5c2">
4
Fill Color: <input id="fill" type="color" value="#ffffff">
5
Text: <input id="text" type="text" value="Text">
6
<lable>
7
Image:<input id="image" type="file"accept="image/png, image/jpeg">
8
ImageColor: <input id="imageColor" type="color" value="#808080">
9
</lable>
10
</div>
11
<canvas width="220" height="190"></canvas>
12
</body>