)
}
}
)
(
}
{
)
)
(
)
(
(
{
}
)
(
)
}
)
)
{
(
(
)
)
}
)
(
}

Oera Linda Inspired Symbols

  1. var canvas = document.createElement("canvas"),
  2.   c = canvas.getContext("2d"),
  3.   title = document.createElement("h1");
  4.  
  5. canvas.style.transformOrigin = "top left";
  6. canvas.style.transform = "scale(0.5, 0.5)";
  7.  
  8. document.body.appendChild(canvas);
  9.  
  10. title.innerHTML = "Oera Linda Inspired Symbols";
  11. document.body.appendChild(title);
  12.  
  13. var erase = function () {
  14.   c.fillStyle = "#244250";
  15.   c.fillRect(0, 0, canvas.width, canvas.height);
  16. };
  17.  
  18. var shuffle = function () {
  19.   return 0.5 - Math.random();
  20. };
  21.  
  22. var Symbol = function (x, y, radius) {
  23.   this.x = x;
  24.   this.y = y;
  25.   this.radius = radius;
  26.   this.halfRadius = this.radius / 2;
  27.   this.draw();
  28. };
  29.  
  30. Symbol.ARC_NUM = 8;
  31. Symbol.TOTAL_SEGS = 23;
  32. Symbol.nodeMap = [
  33.   // [node index][list of possible node connections]
  34.   [7, 0, 9],
  35.   [10, 0, 2],
  36.   [11, 3, 1],
  37.   [4, 2, 12],
  38.   [3, 5, 13],
  39.   [4, 6, 14],
  40.   [5, 7, 15],
  41.   [6, 0, 16],
  42.   [0, 9],
  43.   [8, 10, 11, 12, 13, 14, 15, 16],
  44.   [1, 9],
  45.   [2, 9],
  46.   [3, 9],
  47.   [4, 9],
  48.   [5, 9],
  49.   [6, 9],
  50.   [7, 9]
  51. ];
  52.  
  53. Symbol.segMap = {
  54.   // [node-node][segment function index]
  55.   "0-1": 0,
  56.   "1-2": 1,
  57.   "2-3": 2,
  58.   "3-4": 3,
  59.   "4-5": 4,
  60.   "5-6": 5,
  61.   "6-7": 6,
  62.   "7-0": 7,
  63.  
  64.   "0-8": 9,
  65.   "8-9": 8,
  66.  
  67.   "9-10": 10,
  68.   "9-11": 12,
  69.   "9-12": 14,
  70.   "9-13": 16,
  71.   "9-14": 18,
  72.   "9-15": 20,
  73.   "9-16": 22,
  74.  
  75.   "1-10": 11,
  76.   "2-11": 13,
  77.   "3-12": 15,
  78.   "4-13": 17,
  79.   "5-14": 19,
  80.   "6-15": 21,
  81.   "7-16": 23
  82. };
  83.  
  84. // add reverse node connection keys
  85. for (var i in Symbol.segMap) {
  86.   var key = i.split("-").reverse().join("-");
  87.   Symbol.segMap[key] = Symbol.segMap[i];
  88. }
  89.  
  90. // store all keys
  91. Symbol.segMapKeys = [];
  92. for (var i in Symbol.segMap) {
  93.   Symbol.segMapKeys.push(i);
  94. }
  95.  
  96. Symbol.prototype = {
  97.   constructor: Symbol,
  98.   arcSegLength: (Math.PI * 2) / Symbol.ARC_NUM,
  99.   mirrors: [
  100.     [-1, -1],
  101.     [1, -1],
  102.     [-1, 1]
  103.   ],
  104.  
  105.   line: function (offset, isInner) {
  106.     var theta = this.arcSegLength * offset,
  107.       cos = Math.cos(theta),
  108.       sin = Math.sin(theta),
  109.       x1 = this.halfRadius * cos,
  110.       y1 = this.halfRadius * sin,
  111.       x2,
  112.       y2;
  113.  
  114.     if (isInner) {
  115.       x2 = 0;
  116.       y2 = 0;
  117.     } else {
  118.       x2 = this.radius * cos;
  119.       y2 = this.radius * sin;
  120.     }
  121.  
  122.     c.beginPath();
  123.     c.moveTo(x1, y1);
  124.     c.lineTo(x2, y2);
  125.     c.stroke();
  126.   },
  127.  
  128.   arc: function (offset) {
  129.     var step = this.arcSegLength * offset;
  130.     c.beginPath();
  131.     c.arc(0, 0, this.radius, step, step + this.arcSegLength, false);
  132.     c.stroke();
  133.   },
  134.  
  135.   drawAll: function () {
  136.     c.save();
  137.     c.translate(this.x, this.y);
  138.     for (var i = 0; i <= Symbol.TOTAL_SEGS; i++) {
  139.       this[i]();
  140.     }
  141.     c.restore();
  142.   },
  143.  
  144.   sequence: function (num) {
  145.     var keys = Symbol.segMapKeys,
  146.       index = Math.floor(keys.length * Math.random()),
  147.       curr = keys[index],
  148.       seq = [curr];
  149.  
  150.     for (var i = 0; i < num; i++) {
  151.       var comp = curr.split("-"),
  152.         end = comp[1],
  153.         begin = comp[0];
  154.  
  155.       for (var j = 0; j < keys.length; j++) {
  156.         var cc = keys[j].split("-");
  157.         if (cc[0] === end && cc[1] !== begin) {
  158.           curr = keys[j];
  159.           seq.push(curr);
  160.           break;
  161.         }
  162.       }
  163.     }
  164.     return seq;
  165.   },
  166.  
  167.   draw: function () {
  168.     var steps = 1 + Math.floor(Math.random() * 5);
  169.     (keys = this.sequence(steps)),
  170.       (indices = []),
  171.       (memory = {}),
  172.       (mirrorProb = 0.3),
  173.       (multiMirrorProb = 0.1),
  174.       (mirrorIter = 1),
  175.       (scales = []);
  176.  
  177.     c.lineWidth = 1;
  178.     c.strokeStyle = "rgba(255,255,255,0.15)";
  179.     this.drawAll();
  180.  
  181.     c.lineWidth = 2;
  182.     c.strokeStyle = "rgb(255,255,255)";
  183.  
  184.     c.save();
  185.     c.translate(this.x, this.y);
  186.     for (var i = 0; i < keys.length; i++) {
  187.       var index = Symbol.segMap[keys[i]];
  188.       this[index]();
  189.       indices.push(index);
  190.     }
  191.     c.restore();
  192.  
  193.     if (Math.random() < mirrorProb) {
  194.       mirrorIter = 1;
  195.  
  196.       if (Math.random() < multiMirrorProb) {
  197.         mirrorIter = 2 + Math.round(Math.random());
  198.       }
  199.  
  200.       scales = this.mirrors.sort(shuffle);
  201.  
  202.       for (var i = 0; i < mirrorIter; i++) {
  203.         c.save();
  204.         c.translate(this.x, this.y);
  205.         c.scale(scales[i][0], scales[i][1]);
  206.         for (var j = 0; j < indices.length; j++) {
  207.           this[indices[j]]();
  208.         }
  209.         c.restore();
  210.       }
  211.     }
  212.   }
  213. };
  214.  
  215. // arc partials:
  216. for (var i = 0; i < Symbol.ARC_NUM; i++) {
  217.   (function (i) {
  218.     Symbol.prototype[i] = function () {
  219.       this.arc(i);
  220.     };
  221.   })(i);
  222. }
  223.  
  224. // line partials:
  225. var j = 0;
  226. for (var i = Symbol.ARC_NUM; i <= Symbol.TOTAL_SEGS; i += 2) {
  227.   // inner
  228.   (function (i, j) {
  229.     Symbol.prototype[i] = function () {
  230.       this.line(j, true);
  231.     };
  232.   })(i, j);
  233.  
  234.   // outer
  235.   (function (i, j) {
  236.     Symbol.prototype[i] = function () {
  237.       this.line(j, false);
  238.     };
  239.   })(i + 1, j);
  240.   j++;
  241. }
  242.  
  243. var render = function () {
  244.   var radius = 70,
  245.     diameter = radius * 2,
  246.     padding = 10,
  247.     size = diameter + padding * 2,
  248.     winWidth = window.innerWidth * 2,
  249.     winHeight = window.innerHeight * 2,
  250.     cols = Math.floor(winWidth / size),
  251.     rows = Math.floor(winHeight / size),
  252.     num = cols * rows,
  253.     offX = Math.abs(winWidth - cols * size) / 2,
  254.     offY = Math.abs(winHeight - rows * size) / 2;
  255.  
  256.   for (var i = cols; i < num; i++) {
  257.     var x = offX + radius + (i % cols) * size;
  258.     var y = offY + radius + parseInt(i / cols) * size;
  259.     var s = new Symbol(x, y, radius);
  260.   }
  261. };
  262.  
  263. var renderTimeout;
  264. var rerender = function () {
  265.   clearInterval(renderTimeout);
  266.   renderTimeout = setTimeout(render, 500);
  267. };
  268.  
  269. var resize = function (e) {
  270.   canvas.width = window.innerWidth * 2;
  271.   canvas.height = window.innerHeight * 2;
  272.   erase();
  273.   if (e) {
  274.     rerender();
  275.   }
  276. };
  277.  
  278. window.addEventListener("resize", resize);
  279. resize();
  280. render();
  281.  
  282. document.addEventListener("click", function () {
  283.   erase();
  284.   render();
  285. });

Always fun to look through old codepen stuff…

See the Pen Better Oera Linda Inspired Symbols by Zevan Rosser (@ZevanRosser) on CodePen.

// canvas
snippet.zone ~ 2021-24 /// {s/z}