Skip to content

Instantly share code, notes, and snippets.

@lablibertario
Forked from anonymous/index.html
Created February 20, 2018 01:06
Show Gist options
  • Save lablibertario/841fc2e526d0cdf967d25f3a93e141fb to your computer and use it in GitHub Desktop.
Save lablibertario/841fc2e526d0cdf967d25f3a93e141fb to your computer and use it in GitHub Desktop.

Revisions

  1. @invalid-email-address Anonymous created this gist Feb 20, 2018.
    2 changes: 2 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,2 @@
    <canvas height="1600" width="1600"></canvas>
    <canvas height="1600" width="1600"></canvas>
    7 changes: 7 additions & 0 deletions lissajous.markdown
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    Lissajous
    ---------
    Inspired by [Vincent Pantaloni](https://twitter.com/panlepan), some Lissajous curve drawing.

    A [Pen](https://codepen.io/libertario/pen/NyYPzr) by [Libertar.io](https://codepen.io/libertario) on [CodePen](https://codepen.io).

    [License](https://codepen.io/libertario/pen/NyYPzr/license).
    179 changes: 179 additions & 0 deletions script.babel
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,179 @@
    console.clear();

    const PI = Math.PI,
    PI2 = PI * 2,
    RATE = 30,
    CVS1 = document.querySelector('canvas:nth-child(1)'),
    CVS2 = document.querySelector('canvas:nth-child(2)'),
    CTX1 = CVS1.getContext('2d'),
    CTX2 = CVS2.getContext('2d'),
    CVS_DI = CVS1.width,
    // How many cols/rows
    COUNT = 8,
    // Padding
    PEN_PAD = CVS_DI * 0.025,
    // Radius
    PEN_RAD = CVS_DI / ((COUNT + 1) * 2),
    // Stroke line width
    STROKE = 2,
    // Indicator radius
    TIP_RAD = 6,
    // Coloring
    COLOR = '#FFF',
    COLOR_OFF = '#333';

    // An input "Pen", influences the x or y of a Group's output
    class Pen {
    constructor({ rate, x, y }) {
    this.di = PEN_RAD * 2;
    this.rad = PEN_RAD * 0.7;
    this.x = x * this.di;
    this.y = y * this.di;
    this.cx = this.x + this.di * 0.5;
    this.cy = this.y + this.di * 0.5;
    this.rateName = rate;
    this.rate = RATE * rate;
    this.position = 0;
    }

    tick() {
    this.progress = this.position / this.rate;
    this._calc();
    this.position++;
    }

    // Setting the coordinates for the tip of the pen
    _calc() {
    let deg = 360 * this.progress;
    this.tipX = this.cx + this.rad * Math.cos(deg * PI / 180);
    this.tipY = this.cy + this.rad * Math.sin(deg * PI / 180);
    }
    }

    // Takes an x pen and y pen and produces an output
    class Group {
    constructor(penX, penY) {
    this.penX = penX;
    this.penY = penY;
    this.tracker = {};
    this.progress = 0;
    }

    tick() {
    // setting the last coordinates for the output line
    this.lastX = this.x;
    this.lastY = this.y;
    // Setting the current coordinates
    this.x = this.penX.tipX + this.penY.x;
    this.y = this.penY.tipY + this.penX.y;
    // Storing the combination so we never redraw
    let key = `${this.lastX}-${this.lastY}-${this.x}-${this.y}`;
    // Setting draw to false if this has already been drawn
    if (this.tracker[key]) this.draw = false;
    // Setting draw to true then storing that this has been drawn
    else { this.tracker[key] = true; this.draw = true };
    // Draw the output and the Pens
    this._draw();
    this.progress++;
    }

    _draw() {
    this._drawPen(this.penX);
    this._drawPen(this.penY);
    this._drawOutput();
    }

    // Take a pen and draw it, its rate, and an indicator of current position
    _drawPen({ rad, di, x, y, cx, cy, tipX, tipY, rateName }) {
    // the circle
    CTX1.lineWidth = STROKE;
    CTX1.strokeStyle = COLOR_OFF;
    CTX1.beginPath();
    CTX1.arc(cx, cy, rad, 0, PI2, false);
    CTX1.stroke();

    // The current position
    CTX1.fillStyle = COLOR;
    CTX1.strokeStyle = COLOR;
    CTX1.beginPath();
    CTX1.arc(tipX, tipY, TIP_RAD, 0, PI2, false);
    CTX1.fill();

    // the rate number
    CTX1.fillStyle = COLOR_OFF;
    CTX1.font = `lighter ${rad * 0.5}px Helvetica`;
    CTX1.textAlign = 'center';
    CTX1.textBaseline = 'middle';
    CTX1.fillText(rateName, cx, cy);
    }

    // Draw the output of the two pens
    _drawOutput() {
    // If it hasnt already been drawn yet,
    // draw the path on the canvas that isnt erased each frame
    if (this.draw) {
    CTX2.lineWidth = STROKE;
    CTX2.strokeStyle = COLOR;
    CTX2.beginPath();
    CTX2.moveTo(this.lastX, this.lastY);
    CTX2.lineTo(this.x, this.y);
    CTX2.stroke();
    }

    // Draw the indicator on the refreshing canvas
    CTX1.fillStyle = COLOR;
    CTX1.beginPath();
    CTX1.arc(this.x, this.y, TIP_RAD, 0, PI2, false);
    CTX1.fill();
    }
    }

    let pensX = [],
    pensY = [],
    groups = [];

    // Generating the pens
    for (let x = 0; x < COUNT; x++) {
    let penX = new Pen({ rate: x + 1, x: x + 1, y: 0 }),
    penY = new Pen({ rate: x + 1, x: 0, y: x + 1 });
    pensX.push(penX);
    pensY.push(penY);
    }

    // Generating the groups
    for (let x = 0; x < pensY.length; x++)
    for (let y = 0; y < pensX.length; y++)
    groups.push(new Group(pensX[x], pensY[y]));

    // Start running
    run();

    function run() {
    // Clear the refreshing canvas
    CTX1.clearRect(0, 0, CVS_DI, CVS_DI);

    // For each pen
    for (let i = 0; i < pensX.length; i++) {
    // Tick them forward to get new coords
    pensX[i].tick();
    pensY[i].tick();

    // Draw the axis
    CTX1.lineWidth = STROKE;
    CTX1.strokeStyle = COLOR_OFF;
    CTX1.beginPath();
    CTX1.moveTo(pensX[i].tipX, 0);
    CTX1.lineTo(pensX[i].tipX, CVS_DI);
    CTX1.stroke();
    CTX1.beginPath();
    CTX1.moveTo(0, pensY[i].tipY);
    CTX1.lineTo(CVS_DI, pensY[i].tipY);
    CTX1.stroke();
    }

    // Tick each group (draws them as well)
    groups.forEach(group => group.tick());

    // Run it again
    requestAnimationFrame(run);
    }
    19 changes: 19 additions & 0 deletions style.scss
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,19 @@
    html, body {
    height: 100%;
    }
    body {
    background: #000;
    }
    canvas {
    width: 800px;
    height: auto;
    max-width: 95%;
    position: absolute;
    display: block;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    &:first-child {
    // background: white;
    }
    }