Penrose Tiles
https://habr.com/post/359244/
by Georg Mierau
HTML
<html>
<style>
html {
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
}
canvas {
margin: 0;
padding: 0;
position: absolute;
z-index: 0;
}
input {
width: 75px;
}
div {
margin: 10px;
padding: 10px 10px 10px 20px;
position: absolute;
z-index: 1;
background: rgba(255, 255, 255, 0.75);
}
</style>
<body>
<canvas id="a"></canvas>
<div>
<p>Canvas size: <input type="number" id="w" value="640"> × <input type="number" id="h" value="640"></p>
<p>Tile colors: <input type="text" id="c1" value="#f1c40f"> <input type="text" id="c2" value="#f39c12"> <input type="text" id="c3" value="#95a5a6"> <input type="text" id="c4" value="#7f8c8d"> <input type="text" id="c5" value="#ecf0f1"> <input type="text" id="c6" value="#bdc3c7"></p>
<p>Line width: <input type="number" id="lw" value="0.5"></p>
<p>Line color: <input type="text" id="lc" value="#fff"></p>
<p>Levels: <input type="number" id="levels" value="3"></p>
</div>
</body>
</html>
CSS
html {
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
}
canvas {
margin: 0;
padding: 0;
position: absolute;
z-index: 0;
}
input {
width: 75px;
}
div {
margin: 10px;
padding: 10px 10px 10px 20px;
position: absolute;
z-index: 1;
background: rgba(255, 255, 255, 0.75);
}
JavaScript
function start()
{
var canvas = document.getElementById("a");
canvas.width = parseInt(document.getElementById("w").value);
canvas.height = parseInt(document.getElementById("h").value);
var b = canvas.getContext("2d");
// начать описание контура
function begin(){b.beginPath();}
// начать линию с точки
function from(p) {b.moveTo(s[8] + p[0], s[9] - p[1]);}
// привести линию к точке
function to(p){b.lineTo(s[8] + p[0], s[9] - p[1]);}
// привести линию к начальной точке, не требуется если выполняется только заливка
function close(){b.closePath();}
// заливка
function fill(color){b.fillStyle = color; b.fill();}
// обводка контура линией
function line(){b.strokeStyle = document.getElementById("lc").value; b.lineWidth = parseInt(document.getElementById("lw").value); b.stroke();}
function line_white(){b.strokeStyle = document.getElementById("lc").value; b.lineWidth = parseInt(document.getElementById("lw").value); b.stroke();}
function line_black(){b.strokeStyle = "#444"; b.lineWidth = 1.5; b.stroke();}
var s;
function prepare()
{
var sqrt = Math.sqrt;
var fi = (sqrt(5) - 1) / 2;
var fb = (sqrt(5) + 1) / 2;
var f3 = sqrt(3 + fi);
var f2 = sqrt(2 - fi);
//координаты базовых векторов для всех десяти направлений
var vt = [[ 2, 0, 0, 0], [ 1, 1, 0, 1], [ 0, 1, 1, 0], [ 0,-1, 1, 0], [-1,-1, 0, 1],
[-2, 0, 0, 0], [-1,-1, 0,-1], [ 0,-1,-1, 0], [ 0, 1,-1, 0], [ 1, 1, 0,-1]];
// Константы множители координат
var c = [1/2, fi/2, f3/2, f2/2]
// Общий массив констант
// нулевой элемент для контекста
// седьмой для дополнительных данных рисования.
// восьмой и девятый для указания центра рисования
// десятый для размера шага.
var s = [0, vt, c, fi, f3, f2, 0, 0, 0, 0];
return s;
}
s = prepare();
s[0] = b;
s[7] = 1; // доля последнего уровня
s[8] = 500/2; // сдвих координаты x
s[9] = 320/2; // сдвиг координаты y
var f = []; // слои разбиения.
f[0] = [];
f[0].push([0,[ 0, 0, 0, 0],0]);
f[0].push([1,[...