I am working on functionality where I have to create a brush-like an effect on the web page.
The requirement is that there will be multiple patterns/textures available in the background. And the user will drag the mouse to create the effect of that pattern on the page.
Below is the JSFiddle link where I have created the structure, I am able to create the pattern, but I am unsure of how to create the brush-like effect.
I have added the brush image as a data source in my JSFiddle Link
I am a beginner in canvas and don't have any idea about how to move forward. Please let me know if I am going in the right direction.
Check the Reference Website
where this functionality is running and working.
I am working on functionality where I have to create a brush-like an effect on the web page.
The requirement is that there will be multiple patterns/textures available in the background. And the user will drag the mouse to create the effect of that pattern on the page.
Below is the JSFiddle link where I have created the structure, I am able to create the pattern, but I am unsure of how to create the brush-like effect.
I have added the brush image as a data source in my JSFiddle Link
I am a beginner in canvas and don't have any idea about how to move forward. Please let me know if I am going in the right direction.
Check the Reference Website
where this functionality is running and working.
- Apologies if my question is very simple, I am a beginner in canvas, I have tried few things but that didn't work. Can anybody give me an idea. – Varun Chakervarti Commented Mar 17, 2019 at 8:11
- 1 So your current brush is an arc from 0 to 10 radians (or about 573 degrees which bees 213 degrees). If you create a brush that is a path, you could just substitute it for the arc you have there now. If you need the brush to be an image, this bees more plicated. – aptriangle Commented Mar 17, 2019 at 13:34
- 1 Well, to use a brush mask with the canvas 2d context, I would draw the brush mask to an offscreen canvas, which would accumulate all the drawings of the brush mask. For each frame I would clear the visible canvas, draw the full pattern image to the visible canvas, then set the blend mode to destination-in and draw the offscreen canvas to the visible canvas, which would remove all the parts of the pattern image that the brush wasn't covering. You could also use PIXI.js like the reference site. – aptriangle Commented Mar 17, 2019 at 16:52
- 1 I made a modification to your code that creates random bristles and then draws them as circles. You will probably want to choose bristle positions so that they are organized in the way you want, not random, but this at least shows how to convert the array of bristle positions into a brush: jsfiddle/z43udtLn – aptriangle Commented Mar 18, 2019 at 16:35
- 2 maybe this helps: github./tennisonchan/fabric-brush – di3 Commented Mar 23, 2019 at 23:14
2 Answers
Reset to default 2Well for a basic brush effect, instead of drawing a single large dot, you can instead draw a bunch of smaller dots, each dot representing a single brush stroke. You can also add variable width to the strokes if you want but that is upto you. This is a basic brush example, instead of drawing a circle, draw it like this: JS Fiddle
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let drawCheck = false;
ctx.strokeStyle = "#808080";
let points = 40;
let offsets = [];
let radius = 50;
let prev = {
x: -1,
y: -1
};
let curr = {
x: -1,
y: -1
};
for (let i = 0; i < points; i++) {
offsets.push([Math.random() * radius * (-1) ** i, Math.random() * radius * (-1) ** i, 1 + Math.random() * 4]);
}
function draw(x, y) {
curr.x = x;
curr.y = y;
if (drawCheck) {
if (prev.x == -1) {
offsets.forEach(offset => {
ctx.beginPath();
ctx.arc(curr.x + offset[0], curr.y + offset[1], 1, 0, 2 * Math.PI);
ctx.fill();
prev.x = curr.x;
prev.y = curr.y;
});
} else {
offsets.forEach(offset => {
ctx.lineWidth = offset[2];
ctx.beginPath();
ctx.moveTo(prev.x + offset[0], prev.y + offset[1]);
ctx.lineTo(curr.x + offset[0], curr.y + offset[1]);
ctx.stroke();
})
prev.x = curr.x;
prev.y = curr.y;
}
}
}
document.addEventListener("mousedown", (e) => drawCheck = true);
document.addEventListener("mousemove", (e) =>
draw(e.clientX, e.clientY));
document.addEventListener("mouseup", (e) => {
drawCheck = false;
prev = {
"x": -1,
"y": -1
};
});
#canvas {
border: 2px solid black;
}
<html>
<head>
</head>
<body>
<canvas id="canvas" height=320 width=600></canvas>
</body>
</html>
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let drawCheck = false;
ctx.strokeStyle = "#808080";
let points = 40;
let offsets = [];
let radius = 50;
let prev = {
x: -1,
y: -1
};
let curr = {
x: -1,
y: -1
};
for (let i = 0; i < points; i++) {
offsets.push([Math.random() * radius * (-1) ** i, Math.random() * radius * (-1) ** i, 1 + Math.random() * 4]);
}
function draw(x, y) {
curr.x = x;
curr.y = y;
if (drawCheck) {
if (prev.x == -1) {
offsets.forEach(offset => {
ctx.beginPath();
ctx.arc(curr.x + offset[0], curr.y + offset[1], 1, 0, 2 * Math.PI);
ctx.fill();
prev.x = curr.x;
prev.y = curr.y;
});
} else {
offsets.forEach(offset => {
ctx.lineWidth = offset[2];
ctx.beginPath();
ctx.moveTo(prev.x + offset[0], prev.y + offset[1]);
ctx.lineTo(curr.x + offset[0], curr.y + offset[1]);
ctx.stroke();
})
prev.x = curr.x;
prev.y = curr.y;
}
}
}
document.addEventListener("mousedown", (e) => drawCheck = true);
document.addEventListener("mousemove", (e) =>
draw(e.clientX, e.clientY));
document.addEventListener("mouseup", (e) => {
drawCheck = false;
prev = {
"x": -1,
"y": -1
};
});
#canvas {
border: 2px solid black;
}
<html>
<head>
</head>
<body>
<canvas id="canvas" height=320 width=600></canvas>
</body>
</html>