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

CoffeeScript Ikeda Map

  1. canvas = document.querySelector "canvas"
  2. c = canvas.getContext "2d"
  3. locX = 120
  4. locY = 400
  5. xn1 = xn = yn1 = yn = tn = 0
  6. u = .7
  7. steps = 10
  8. iterations = 200
  9. scale = 180
  10.  
  11. c.fillStyle = "black"
  12. c.fillRect 0, 0, canvas.width, canvas.height
  13. c.fillStyle = "rgba(255,255,255,0.2)"
  14.  
  15. run = setInterval ->
  16.   clearInterval run if u > 1
  17.   i = 0
  18.  
  19.   while i < steps
  20.     u += 0.00015
  21.     j = 0
  22.  
  23.     while j < iterations
  24.       xn = xn1
  25.       yn = yn1
  26.       tn = 0.4 - (6 / (1 + xn * xn + yn * yn))
  27.       xn1 = 1 + u * (xn * Math.cos(tn) - yn * Math.sin tn)
  28.       yn1 = u * (xn * Math.sin(tn) + yn * Math.cos tn)
  29.       c.fillRect locX + xn1 * scale, locY + yn1 * scale, 1, 1
  30.       j++
  31.     i++
  32. , 30

I do quite miss CoffeeScript sometimes… here is an old codepen of the Ikeda Map:

See the Pen Ikeda Map by Zevan Rosser (@ZevanRosser) on CodePen.

Little Galaxy ES5

  1. var canvas = document.createElement('canvas'), 
  2.     c = canvas.getContext('2d'), 
  3.     SIZE = 350;
  4.  
  5. canvas.width = SIZE;
  6. canvas.height = SIZE;
  7.  
  8. document.body.appendChild(canvas);
  9.  
  10. c.fillStyle = 'black';
  11. c.fillRect(0, 0, SIZE, SIZE);
  12.  
  13. c.fillStyle = 'white';
  14.  
  15. var spa = function(ts) {
  16.   var r = 0, t =  0;
  17.   var jitterX, jitterY, jitterT, jitterR;
  18.   for (var i = 0; i < 100; i += 0.5) {
  19.     t = ts + i / 15;
  20.     r = i;
  21.     jitterR = 5 + i / 5;
  22.     jitterT = Math.random() * 2 * Math.PI;
  23.     jitterX = Math.random() * jitterR * Math.sin(jitterT);
  24.     jitterY = Math.random() * jitterR * Math.cos(jitterT);
  25.     c.fillStyle = `hsl(${t / Math.PI * 180}deg, 50%, 50%)`;
  26.     c.fillRect(
  27.       SIZE / 2 + r * Math.cos(t) + jitterX,
  28.       SIZE / 2 + r * Math.sin(t) + jitterY, 
  29.       3, 3
  30.     );
  31.   }
  32. }
  33.  
  34. spa(0);
  35. spa(Math.PI);

I made this in response to a question from a friend of mine a few years back…

Old Codepen 2013

  1. $(function () {
  2.   var canvas = $("<canvas>").appendTo("body"),
  3.     win = $(window),
  4.     cnvs = canvas[0],
  5.     c = cnvs.getContext("2d"),
  6.     el = $("<div>"),
  7.     letters = [],
  8.     NUM = 10,
  9.     TWO_PI = Math.PI * 2;
  10.  
  11.   c.font = "16px sans-serif";
  12.  
  13.   win
  14.     .resize(function () {
  15.       cnvs.width = win.width();
  16.       cnvs.height = win.height();
  17.       c.fillStyle = "white";
  18.       c.fillRect(0, 0, cnvs.width, cnvs.height);
  19.     })
  20.     .trigger("resize");
  21.  
  22.   function symbol() {
  23.     var r = parseInt(Math.random() * 9999),
  24.       s = "&#" + r + ";";
  25.     el.html(s);
  26.     return el.html();
  27.   }
  28.  
  29.   function Letter() {}
  30.  
  31.   Letter.prototype.init = function () {
  32.     this.x = Math.random() * win.width();
  33.     this.y = Math.random() * win.height();
  34.  
  35.     this.sym = symbol();
  36.     this.rot = Math.random() * 2 * Math.PI;
  37.     this.rotVel = Math.random() * 0.02 - 0.01;
  38.  
  39.     this.size = 1 + Math.random() * 10;
  40.     this.sizeVel = Math.random() * 0.2;
  41.     this.col = ["black", "white", "#999"][parseInt(Math.random() * 3)];
  42.  
  43.     this.rad = Math.random();
  44.     this.vx = this.rad * Math.cos(Math.random() * TWO_PI);
  45.     this.vy = this.rad * Math.sin(Math.random() * TWO_PI);
  46.  
  47.     this.life = 0;
  48.     this.maxLife = parseInt(Math.random() * 200);
  49.  
  50.     if (Math.random() < 0.1) {
  51.       this.doGrad = true;
  52.       this.channel = parseInt(Math.random() * 200);
  53.     }
  54.  
  55.     this.shadow = false;
  56.     if (Math.random() < 0.1) {
  57.       this.shadow = true;
  58.     }
  59.   };
  60.  
  61.   Letter.prototype.run = function () {
  62.     if (this.doGrad) {
  63.       this.channel += 1;
  64.  
  65.       this.col =
  66.         "rgb(" + this.channel + "," + this.channel + "," + this.channel + ")";
  67.     }
  68.  
  69.     if (this.shadow == true) {
  70.       c.shadowBlur = 100;
  71.       c.shadowColor = "rgba(76,105,135,0.2)";
  72.     }
  73.  
  74.     this.size += this.sizeVel;
  75.     this.rot += this.rotVel;
  76.     this.x += this.vx;
  77.     this.y += this.vy;
  78.  
  79.     c.save();
  80.  
  81.     c.translate(this.x, this.y);
  82.     c.scale(this.size, this.size);
  83.     c.rotate(this.rot);
  84.  
  85.     c.fillStyle = this.col;
  86.     c.fillText(this.sym, -this.size / 2, -this.size / 2);
  87.  
  88.     c.restore();
  89.  
  90.     this.life++;
  91.  
  92.     if (this.life >= this.maxLife) {
  93.       this.init();
  94.       //console.log("respurn");
  95.     }
  96.   };
  97.  
  98.   for (var i = 0; i < NUM; i++) {
  99.     var letter = (letters[i] = new Letter());
  100.     letter.init();
  101.   }
  102.  
  103.   setInterval(function () {
  104.     for (var i = 0; i < NUM; i++) {
  105.       letters[i].run();
  106.     }
  107.   }, 30);
  108. });

It’s fun to look through old code….

See the Pen Symbolz by Zevan Rosser (@ZevanRosser) on CodePen.

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

Canvas Ring on Image

  1. const uploadInput = document.body.appendChild(
  2.   Object.assign(document.createElement('input'), {
  3.     type: 'file',
  4.     accept: 'image/png, image/jpeg'
  5.   })
  6. )
  7. uploadInput.style.display = 'block'
  8.  
  9. const canvas = document.body.appendChild(document.createElement('canvas'))
  10. const c = canvas.getContext('2d')
  11.  
  12. canvas.style.width = '70%'
  13.  
  14. let sampleSize
  15. const steps = 100
  16. const step = (Math.PI * 2) / steps
  17.  
  18. let interval
  19.  
  20. const ring = () => {
  21.   clearInterval(interval)
  22.   let x = imageEl.width / 2,
  23.     y = imageEl.height / 2,
  24.     rad = imageEl.width * 0.3,
  25.     theta = 0,
  26.     px,
  27.     py,
  28.     pxs = [],
  29.     spy = []
  30.   ;(pys = []), (im = []), (rects = [])
  31.  
  32.   for (let i = 0; i < steps; i++) {
  33.     px = x + rad * Math.cos(theta)
  34.     py = y + (rad / 2) * Math.sin(theta)
  35.     theta += step
  36.     pxs[i] = px
  37.     pys[i] = spy[i] = py
  38.     im[i] = c.getImageData(px, py, sampleSize, sampleSize)
  39.     rects[i] = [px, py, sampleSize, sampleSize]
  40.   }
  41.  
  42.   interval = setInterval(() => {
  43.     for (let i = 0; i < steps; i++) {
  44.       pys[i] -= 1
  45.       c.putImageData(im[i], pxs[i], pys[i])
  46.       v = (y - spy[i]) / rad
  47.       c.fillStyle = 'rgba(0,0,0,' + v + ')'
  48.       c.fillRect(pxs[i] - 1, pys[i], sampleSize + 2, sampleSize - 1)
  49.     }
  50.   }, 16)
  51. }
  52.  
  53. const imageEl = new Image()
  54. imageEl.src = 'https://snippet.zone/wp-content/uploads/2022/01/taho-scaled.jpg'
  55. imageEl.onload = () => {
  56.   canvas.width = imageEl.width
  57.   canvas.height = imageEl.height
  58.   c.drawImage(imageEl, 0, 0)
  59.   sampleSize = imageEl.width / 25
  60.  
  61.   ring()
  62. }
  63.  
  64. const reader = new FileReader()
  65.  
  66. reader.addEventListener('load', () => {
  67.   imageEl.src = reader.result
  68. })
  69.  
  70. uploadInput.addEventListener('change', e => {
  71.   const file = e.target.files[0]
  72.   if (file != null) {
  73.     reader.readAsDataURL(file)
  74.   }
  75. })

Upload an image and it will have a distortion ring drawn on it

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