3

Based on this question : Question, I tried to create a flower of life.

So far I got the 7 first petals but to create the rest of the flower (19 petals) I'm stuck because I can't figure out what I'm doing wrong.

I'm not so good in Maths and don't exactly understand how to proceed.

Code so far (Limited to 8 circles):

window.addEventListener('load', function () {
    let distanceX = 75,
        distanceY = 75,
        angle = 60,
        circles = 8;
    for (var i = 0; i < circles; i++) {
        let div = document.createElement('div');
        div.id = 'c' + i;
        div.className = 'circle';
        document.getElementById('fol').appendChild(div);
        let circle = document.getElementById('c' + i);
        if (i == 0) {
            circle.style.transform = "translate(" + 0 + "px," + 0 + "px)";
        } else {
            if (i > 6) {
                let j = i - 2,
                    k = i - 1;
                let previouscircle = document.getElementById('c' + j).getBoundingClientRect();
                let lastcircle = document.getElementById('c' + k).getBoundingClientRect();
                var x0 = previouscircle.left;
                var y0 = previouscircle.top;
                var x1 = lastcircle.left;
                var y1 = lastcircle.top;
                
                console.log("previous (" + j + ") " + x0 + " " + y0);
                console.log("last (" + k + ") " + x1 + " " + y1);

                function intersection(x0, y0, r0, x1, y1, r1) {
                    var a, dx, dy, d, h, rx, ry;
                    var x2, y2;

                    dx = x1 - x0;
                    dy = y1 - y0;
                    d = Math.sqrt((dy * dy) + (dx * dx));
                    a = ((r0 * r0) - (r1 * r1) + (d * d)) / (2.0 * d);
                    x2 = x0 + (dx * a / d);
                    y2 = y0 + (dy * a / d);
                    h = Math.sqrt((r0 * r0) - (a * a));
                    rx = -dy * (h / d);
                    ry = dx * (h / d);

                    var xi = x2 + rx;
                    var xi_prime = x2 - rx;
                    var yi = y2 + ry;
                    var yi_prime = y2 - ry;

                    return [xi, xi_prime, yi, yi_prime];
                }
                let result = intersection(x0, y0, distanceX, x1, y1, distanceY); 
                let resultX = result[1];
                let resultY = result[3];
                circle.style.left = resultX + "px";
                circle.style.top = resultY + "px";
            }
            circle.style.transform = "translate(" + distanceX * Math.cos(Math.PI / 180 * angle * i) + "px," + distanceY * Math.sin(Math.PI / 180 * angle * i) + "px)";
        }

        let limits = circle.getBoundingClientRect();
        console.log("c" + i + " " + limits.left + " " + limits.top);
    }
});
body {
    margin: 0;
    background-color: black;
}

.container {
    width: 100vw;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}

.circle {
    width: 150px;
    height: 150px;
    position: absolute;
    border-radius: 100%;
    background-color: rgba(255, 255, 255, 0.1);
    box-shadow: 0 0 10px rgba(255, 255, 255, 1);
}
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>Flower of life</title>
    <!--
    <link rel="stylesheet" type="text/css" href="fol.css" />
    -->
</head>

<body>
    <div class="background">
        <div id="fol" class="container">
        </div>
    </div>
    <!--
    <script src="fol.js"></script>
    -->
</body>

</html>

Result I try to achieve:

enter image description here

1 Answers1

2

Code cleaned up :-)

window.addEventListener('load', function () {
let distanceX = 75,
    distanceY = 75,
    angle = 60,
    circles = 19;
for (var i = 0; i <= circles; i++) {
    let div = document.createElement('div');
    div.id = 'c' + i;
    div.className = 'circle';
    document.getElementById('fol').appendChild(div);
    let circle = document.getElementById('c' + i);
    if (i == 0) {
        circle.style.transform = "translate(" + 0 + "px," + 0 + "px)";
    } else {
        circle.style.transform = "translate(" + distanceX * Math.cos(Math.PI / 180 * angle * i) + "px," + distanceY * Math.sin(Math.PI / 180 * angle * i) + "px)";
    }
}
function intersection(x0, y0, r0, x1, y1, r1) {
    var a, dx, dy, d, h, rx, ry;
    var x2, y2;

    dx = x1 - x0;
    dy = y1 - y0;
    d = Math.sqrt((dy * dy) + (dx * dx));
    a = ((r0 * r0) - (r1 * r1) + (d * d)) / (2.0 * d);
    x2 = x0 + (dx * a / d);
    y2 = y0 + (dy * a / d);
    h = Math.sqrt((r0 * r0) - (a * a));
    rx = -dy * (h / d);
    ry = dx * (h / d);
    var xi = x2 + rx;
    var yi = y2 + ry;
    return [xi, yi];
}
for (var f = 7; f <= 18; f++) {
    let j = f,
        k = f + 1;
    let previouscircle = document.getElementById('c' + j).getBoundingClientRect();
    let lastcircle = document.getElementById('c' + k).getBoundingClientRect();
    var x0 = previouscircle.left;
    var y0 = previouscircle.top;
    var x1 = lastcircle.left;
    var y1 = lastcircle.top;
    if (f < 13) {
        distanceX = 75;
        distanceY = 0.1;
    } else {
        distanceX = 0.1;
        distanceY = 75;
    }
    let result = intersection(x0, y0, distanceX, x1, y1, distanceY);
        let resultX = result[0];
        let resultY = result[1];
        let circle = document.getElementById('c' + f);
        circle.style.left = resultX + "px";
        circle.style.top = resultY + "px";
}
document.getElementById('c' + circles).remove();
});
body {
    margin: 0;
    background-color: black;
}

.container {
    width: 100vw;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}

.circle {
    width: 150px;
    height: 150px;
    position: absolute;
    border-radius: 100%;
    background-color: rgba(255, 255, 255, 0.1);
    box-shadow: 0 0 10px rgba(255, 255, 255, 1);
}
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>Flower of life</title>
    <link rel="stylesheet" type="text/css" href="fol.css" />
</head>

<body>
    <div class="background">
        <div id="fol" class="container">
        </div>
    </div>

    <script src="fol.js"></script>
</body>

</html>
  • I think you need `i <= circles` and `r <= 12` as your for-loop tests... – Nick Aug 29 '22 at 08:08
  • Thank you Nick, that's what I thought too but it's not the solution. If I increase i to 13 (0-12), the 3d round begins. If I increase r, an error is trown... – Claude Dumont Aug 29 '22 at 08:37
  • If you modify your snippet with those changes that does produce the 13th circle... Note I also changed your `if (i > 6) { ... } if (i > 12) { ... }` to `if (i <= 6) { ... } else { ... }` to change the colours – Nick Aug 29 '22 at 08:41
  • Yes, you can't increase `r` without increasing `i` as well – Nick Aug 29 '22 at 08:42
  • You are right about that but 1 circle is already from the next round and drawn twice then. I think it's because I need two circles to draw one, that's why the last one is not drawn. I'll try to pass the value twice, I guess that'll do the trick. – Claude Dumont Aug 29 '22 at 08:48
  • Got it :-) Feels like cheating to remove the last one but it's working now. – Claude Dumont Aug 29 '22 at 08:58
  • 1
    Probably is cheating but results are results! :) – Nick Aug 29 '22 at 09:00
  • Edited the snippet for the full 3 rounds. Thank you for your help. – Claude Dumont Aug 29 '22 at 09:15
  • 1
    Looks great. Glad I could help (even if only a little) – Nick Aug 29 '22 at 09:16