Pull to refresh

Т-фракталы на JavaScript Canvas

Reading time2 min
Views10K
Сегодня я прочитал пост пользователя celen и вдохновился красотой T-фракталов. Так как я немного увлекаюсь созданием растровых композиций в JavaScript Canvas, то у меня возникла идея реализовать то же самое, только на стороне клиента силами JS, освобождая сервер от нагрузки.

В теле HTML-документа необходимо создать тег <canvas>:
<canvas id="canvas"></canvas>

Он достаточно своеобразен: по-умолчанию имеет размер 300х150. Новые размеры ему лучше задавать из javascript.
var canva = document.getElementById('canvas');
canva.width = window.innerWidth;
canva.height = window.innerHeight;
var ctx = canva.getContext('2d');

Теперь определим несколько вспомогательных функций.
function clear() {
    ctx.clearRect(0, 0, canva.width, canva.height);
    ctx.fillStyle = 'rgba(0,0,0,1)';
    ctx.fillRect(0, 0, canva.width, canva.height);
}

Функция clear() очищает всю рабочую область. Зачем там сразу clearRect и полная заливка fillRect? А чтоб наверняка.

Следующая функция отвечает за вывод одиночного узора заданного размера в указанном месте. Сам узор описан с помощью двумерного массива figure размером NxN, элементы которого принимают значения 0 и 1 (0 — прозрачный блок, 1 — цветной блок).
function PrintFigure(x, y, size, style) {
    var sizeElem = Math.floor(size / N);
    for (var i = 0; i < N; i++)
        for (var k = 0; k < N; k++)
            if (figure[i][k] == 1) {
                ctx.fillStyle = style;
                ctx.fillRect(x + i * sizeElem, y + k * sizeElem, sizeElem, sizeElem);
            }
}

При просчете координат и размеров нужно быть внимательным и усекать потенциально-нецелые числа.

Границами рисования у нас будут границы канвы.
var MAX_X = canva.width,
    MAX_Y = canva.height;

За них придется немного выходить, чтобы получить ровное сплошное изображение.

И, наконец, функция, которая рисует узор в заданной области, до тех пор, пока он в нее [область] помещается.
function CreateTFractal() {
    clear();
    var size = N;
    var countByX = Math.floor(MAX_X / size),
    countByY = Math.floor(MAX_Y / size);
	
    while ((countByX > 0) && (countByY > 0)) { // пока рисунок помещается в область
        for (var i = 0; i <= countByX; i++) {
            for (var k = 0; k <= countByY; k++) {
                PrintFigure(i * size, k * size, size, 'rgba(255, 255, 255, 0.3)'); 
            } // k
        } // i
	
        size *= 2; // новый размер для следующей итерации
        countByX = Math.floor(MAX_X / size),
        countByY = Math.floor(MAX_Y / size);
    }
}

Условие И в цикле while по-идее можно заменить на ИЛИ.

демонстрация / скачать HTML-страницу и JS-код архивом

Поитерационная отрисовка изображения (слева направо и сверху вниз):



Стоит уделить немного внимания возможности сохранить изображение с <canvas> в PNG силами javascript:
window.open(document.getElementById("canvas").toDataURL("image/png"),"tfract_save");

Недостатком такого способа является ограничение длины строки адреса.

Вот и всё. Остальной код — банальная обработка форм и контролов.
Tags:
Hubs:
+21
Comments6

Articles

Change theme settings