CREATING ANIMATION "MOVE ALONG CURVE"

<!DOCtype html>
<html>
  <style>
   * {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  width: 100%;
}

body {
  margin: 0;
  overflow: hidden;
}
  </style>
<body>
<script>  
   "use strict";
function getFullScreenParams(ctx) {
    const { width, height } = ctx.canvas;
    return [0, 0, width, height];
}
function getCtxUtils(ctx) {
    function clear() {
        const params = getFullScreenParams(ctx);
        ctx.clearRect(...params);
    }
    function save(callback) {
        ctx.save();
        callback();
        ctx.restore();
    }
    function drawPath(callback) {
        ctx.beginPath();
        callback();
        ctx.closePath();
    }
    return {
        clear,
        save,
        drawPath
    };
}
function initCanvas(resizeCallback, parent = document.body) {
    function create() {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        return [canvas, ctx];
    }
    function resize() {
        const { clientHeight, clientWidth } = parent;
        canvas.height = clientHeight;
        canvas.width = clientWidth;
        resizeCallback();
    }
    function append() {
        parent.innerHTML = '';
        parent.appendChild(canvas);
    }
    const [canvas, ctx] = create();
    resize();
    append();
    window.addEventListener('resize', resize);
    return ctx;
}
class Curve {
    constructor(origin, angle, length = 400) {
        this.angle = angle;
        this.length = length;
        this._angleOffset = 40;
        this.percentage = 0;
        this.speed = (Math.random() * 0.005) + 0.0005;
        this.randColor = () => {
            const { floor, random } = Math;
            return ['cyan', 'magenta', 'yellow'][floor(random() * 3)];
        };
        this.getEndPoint = () => {
            const { cos, sin } = Math;
            const x = cos(this.angle) * this.length;
            const y = sin(this.angle) * this.length;
            return [x, y];
        };
        this.getStartControlPoint = () => {
            const { cos, sin } = Math;
            const angle = this.angle - (this._angleOffset / 60);
            const length = this.length / 3;
            const x = cos(angle) * length;
            const y = sin(angle) * length;
            return [x, y];
        };
        this.getEndControlPoint = () => {
            const { cos, sin } = Math;
            const angle = this.angle + (this._angleOffset / 60);
            const length = (this.length / 3) * 2;
            const x = cos(angle) * length;
            const y = sin(angle) * length;
            return [x, y];
        };
        this.animate = () => {
            function getXY() {
                const x = cubicN(percentage, 0, startControlPoint[0], endControlPoint[0], end[0]);
                const y = cubicN(percentage, 0, startControlPoint[1], endControlPoint[1], end[1]);
                return [x, y];
            }
            // cubic helper formula
            function cubicN(T, a, b, c, d) {
                const t2 = T * T;
                const t3 = t2 * T;
                return a + (-a * 3 + T * (3 * a - a * T)) * T + (3 * b + T * (-6 * b + b * 3 * T)) * T + (c * 3 - c * 3 * T) * t2 + d * t3;
            }
            const { startControlPoint, endControlPoint, end, percentage } = this;
            if (!this.isComplete) {
                this.percentage += this.speed;
                this.currentPoint = getXY();
            }
        };
        this.start = origin;
        this.currentPoint = [0, 0];
        this.end = this.getEndPoint();
        this.startControlPoint = this.getStartControlPoint();
        this.endControlPoint = this.getEndControlPoint();
        this.color = this.randColor();
    }
    get isComplete() {
        return this.percentage >= 1;
    }
}
class Burst {
    constructor(x, y) {
        this.curves = [];
        this.render = (ctx) => {
            function renderCurve(curve) {
                const { currentPoint, endControlPoint, startControlPoint, end } = curve;
                save(() => {
                    drawPath(() => {
                        ctx.moveTo(0, 0);
                        ctx.strokeStyle = 'rgba(80,80,80,0.4)';
                        ctx.bezierCurveTo(...startControlPoint, ...endControlPoint, ...end);
                        ctx.stroke();
                    });
                });
                save(() => {
                    ctx.translate(x, y);
                    drawPath(() => {
                        let [xi, yi] = currentPoint;
                        xi -= x;
                        yi -= y;
                        ctx.fillStyle = curve.color;
                        ctx.moveTo(0, 0);
                        ctx.arc(xi, yi, 4, 0, Math.PI * 2);
                        ctx.fill();
                    });
                });
            }
            function renderCurves() {
                save(() => {
                    ctx.translate(x, y);
                    curves.forEach(renderCurve);
                });
            }
            function renderBackground() {
                save(() => {
                    ctx.translate(0, 0);
                    ctx.fillStyle = '#101219';
                    drawPath(() => ctx.fillRect(...getFullScreenParams(ctx)));
                });
            }
            const { clear, save, drawPath } = getCtxUtils(ctx);
            const { curves, x, y } = this;
            clear();
            renderBackground();
            renderCurves();
        };
        this._x = x;
        this._y = y;
        this.create();
    }
    get x() { return this._x; }
    set x(value) {
        this._x = value;
        if (this.onPositionChange)
            this.onPositionChange();
    }
    get y() { return this._y; }
    set y(value) {
        this._y = value;
        if (this.onPositionChange)
            this.onPositionChange();
    }
    create() {
        const chunkSize = 6 / 32;
        for (let i = 0; i <= 6; i += chunkSize) {
            this.curves.push(new Curve([this.x, this.y], i, 1300));
        }
    }
}
window.onload = init;
function init() {
    function animate() {
        burst.curves.forEach((curve, i) => {
            if (curve.isComplete) {
                const chunkSize = 6 / 32;
                const newCurve = new Curve([burst.x, burst.y], i * chunkSize, 1300);
                burst.curves.splice(i, 1, newCurve);
            }
            else {
                curve.animate();
            }
        });
        burst.render(ctx);
        requestAnimationFrame(animate);
    }
    let [cx, cy] = [window.innerWidth / 2, window.innerHeight / 2];
    const burst = new Burst(cx, cy);
    const ctx = initCanvas(() => {
        [cx, cy] = [window.innerWidth / 2, window.innerHeight / 2];
        burst.x = cx;
        burst.y = cy;
    });
    burst.render(ctx);
    requestAnimationFrame(animate);
}

  </script>

<h1>
   <span>MADE BY DEVANSH MISHRA</span>
       </h1>
</body>
</html>

Comments

Popular posts from this blog

Chandrayan 3 Mission Special :Animation

Python Advance Programs by Devansh Mishra.

Some Basic HTML Codes for Beginners