Skip to content
Advertisement

Create flower of life with intersection formula in Javascript

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

Advertisement

Answer

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>
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement