Sierpiński Triangle

Rendering the Sierpiński triangle using the chaos game method.

HTML5 canvas disabled?

triangle.js

raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
BSD Zero Clause License

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/

window.addEventListener('load', function() {
    'use strict';
    var canvas = document.getElementById("triangleCanvas");
    var ctx = canvas.getContext("2d");

    var reqAnimFrame =
        window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        function (callback) {
            return setTimeout(callback, 1);
        };

    ctx.clearRect(0, 0, canvas.width, canvas.height);

    function rand(max) {
        return Math.floor(Math.random() * max);
    }

    // given list of points produce function to take a point and return next chaos point
    function chaosForge(verts) {
        return function(curPoint) {
            // pick a vertex
            var rndVert = verts[rand(verts.length)];
            // half way from current to random
            return {
                x : curPoint.x + (rndVert.x - curPoint.x) / 2,
                y : curPoint.y + (rndVert.y - curPoint.y) / 2
            };
        };
    }

    function getPointPlotter() {
        var points, currentPoint, nextPointFunc;

        points = [
            {x : 0.5, y : 0.0},
            {x : 0, y : 1},
            {x : 1, y : 1}
        ];

        nextPointFunc = chaosForge(points);

        currentPoint = {x : 0, y : 1};

        return function () {
            var width = Math.min(canvas.height, canvas.width);
            var height = Math.sqrt(3) * width / 2;
            var offX = (canvas.width - width) / 2;
            var offY = (canvas.height - height) / 2;
            // move current point
            currentPoint = nextPointFunc(currentPoint);
            // draw
            ctx.fillRect(currentPoint.x * (width - 1) + offX,
                currentPoint.y * (height - 1) + offY, 1, 1);
        };
    }

    var plotPoint = getPointPlotter();

    function render() {
        var i;
        if (canvas.width != canvas.clientWidth ||
            canvas.height != canvas.clientHeight) {
            canvas.width = canvas.clientWidth;
            canvas.height = canvas.clientHeight;
            plotPoint = getPointPlotter();
        }
        ctx.fillStyle = "darkred";
        for (i = 0; i < 30; i += 1) {
            plotPoint();
        }

        // and again
        reqAnimFrame(render);
    }

    render();
});