Reputation: 8205
I have a main circle in the center. There are circles that are outside this that are always just touching the main circle. Outside circles can overlap each other.
Outside circles can have any line width, and for outside circles that have a smaller line width than the center circle, I'm trying to "eat into" the main circle.
If there were no overlapping circles, I could just set the outside circles to fill, which will eat in at the main circle. However, outside circles can overlap and filling them may break other outside circles.
Here's a picture to explain better:
Here's a snippet showing the above example:
var canvas = document.getElementById("my-canvas"),
ctx = canvas.getContext("2d");
canvas.width = $(window).width();
canvas.height = $(window).height();
drawCircle(174, 174, 100, 20);
drawCircle(300, 300, 75, 15);
drawCircle(400, 400, 66, 5);
drawCircle(325, 423, 50, 7);
function drawCircle(circleCenterX, circleCenterY, circleRadius, lineWidth) {
ctx.beginPath();
ctx.lineWidth = lineWidth;
//canvasContext.fillStyle = "#22313f";
ctx.arc(circleCenterX, circleCenterY, circleRadius, getRadiansFromPercentage(0), getRadiansFromPercentage(1)); // centerX, centerY, radius, startRadians, endRadians
ctx.stroke();
}
function getRadiansFromPercentage(percentage) {
var radians = (percentage * 360) * (Math.PI / 180); // turn percentage to degrees, then to radians
return radians - 0.5 * Math.PI; // - 0.5 * Math.PI so "0.00" starts at the top of the circle
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="my-canvas"></canvas>
The end goal is for my project to look something like this:
Upvotes: 0
Views: 149
Reputation: 54026
To do this you first draw the center circle as normal, then draw all the outside circles filled using ctx.globalCompositeOperation = "destination-out"
this will remove pixels from the center circle. When all the outside circles rendered then set ctx.globalCompositeOperation = "source-over"
and render the outside circles as normal.
Example code with random circles. I think this is what you are after.
canvas.width = 512;
canvas.height = 512;
const ctx = canvas.getContext("2d");
const circle = {
x : 256,
y : 256,
r : 150,
w : 10,
}
const circles = [];
function randCircle(){
const ang = Math.random() * Math.PI * 2;
const r = Math.random() * 100 + 50;
const w = Math.random() * 18 + 2;
const dist = circle.r - circle.w/2 + (r - w/2 );
circles.push({
x : circle.x + Math.cos(ang) * dist,
y : circle.y + Math.sin(ang) * dist,
r,
w,
})
}
function doit(){
ctx.clearRect(0,0,512,512);
circles.length = 0;
/// some random circles
for(let i = 0; i < 8; i ++){
randCircle();
}
function renderAll(){
ctx.lineWidth = circle.w;
ctx.beginPath();
ctx.arc(circle.x, circle.y, circle.r, 0 , Math.PI * 2);
ctx.stroke();
ctx.globalCompositeOperation = "destination-out";
ctx.beginPath();
for(var i = 0; i < circles.length; i ++){
var c = circles[i];
ctx.moveTo(c.x + c.r,c.y);
ctx.arc(c.x,c.y,c.r,0,Math.PI * 2);
}
ctx.fill();
ctx.globalCompositeOperation = "source-over";
for(var i = 0; i < circles.length; i ++){
ctx.beginPath();
var c = circles[i];
ctx.lineWidth = c.w;
ctx.arc(c.x,c.y,c.r,0,Math.PI * 2);
ctx.stroke();
}
}
renderAll();
}
canvas.onclick = doit;
doit();
canvas {
border : 2px solid black;
}
Click canvas to randomise.<br>
<canvas id="canvas"></canvas>
Upvotes: 1