<div id='root' class='my-example'></div>
.my-example {
    height: 100vh;
}

.my-example > svg {
    display: block;
    height: 100%;
    width: 100%;
}
const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';

class MathUtils {
    static clamp(value, min, max) {
        return Math.min(Math.max(value, min), max);
    }
}

class Example {
    #root;
    #svg;
    #path;
    #x;
    #y;
    #mouseX;
    #mouseY;
    #frameRequestID;

    constructor(root) {
        this.#root = root;
        this.#init();
        this.#initEventListeners();
    }

    #init() {
        this.#svg = document.createElementNS(SVG_NAMESPACE, 'svg');
        this.#path = document.createElementNS(SVG_NAMESPACE, 'path');
        this.#path.setAttribute('stroke', '#000');
        this.#path.setAttribute('fill', 'none');
        this.#path.setAttribute('stroke-width', '1');
        this.#path.setAttribute('stroke-linejoin', 'round');
        this.#path.setAttribute('stroke-linecap', 'round');
        this.#svg.appendChild(this.#path);
        this.#mouseX = window.innerWidth / 2;
        this.#mouseY = window.innerHeight / 2;
        this.#x = this.#mouseX;
        this.#y = this.#mouseY;
        this.#updateSVG();
        this.#root.appendChild(this.#svg);
    }

    #updateSVG() {
        const width = window.innerWidth;
        const height = window.innerHeight;
        const s = Math.min(width, height) / 4;
        const dx = this.#x - this.#mouseX;
        const dy = this.#y - this.#mouseY;

        this.#x -= dx / 100;
        this.#y -= dy / 100;

        const x = MathUtils.clamp(this.#x, s, width - s);
        const y = MathUtils.clamp(this.#y, s, height - s);

        this.#svg.setAttribute('viewBox', `0 0 ${width} ${height}`);

        this.#path.setAttribute('d', `
            M ${x} ${y - s}
            L ${x + s} ${y + s}
            L ${x - s} ${y + s}
            L ${x} ${y - s}

            L ${width} 0
            L ${x + s / 2} ${y}
            L ${width} ${height / 2}
            L ${x + s} ${y + s}
            L ${width} ${height}

            M ${x + s} ${y + s}
            L ${width * (2 / 3)} ${height}
            L ${x} ${y + s}
            L ${width / 3} ${height}
            L ${x - s} ${y + s}
            M 0 ${height}

            L ${x - s} ${y + s}
            L 0 ${height / 2}
            L ${x - s / 2} ${y}
            L 0 0
            L ${x} ${y - s}
        `);
    }

    #initEventListeners() {
        window.addEventListener('resize', this.#onWindowResize.bind(this));
        document.addEventListener('mousemove', this.#onMouseMove.bind(this));
        this.#root.addEventListener('mouseleave', this.#onMouseLeave.bind(this));
    }

    #onWindowResize() {
        this.#updateSVG();
    }

    #onMouseMove(e) {
        this.#mouseX = e.clientX;
        this.#mouseY = e.clientY;
    }

    #onMouseLeave() {
        this.#mouseX = window.innerWidth / 2;
        this.#mouseY = window.innerHeight / 2;
    }

    start() {
        this.#updateSVG();

        this.#frameRequestID = requestAnimationFrame(this.start.bind(this));
    }

    stop() {
        cancelAnimationFrame(this.#frameRequestID);
    }
}

function main() {
    const root = document.getElementById('root');
    const example = new Example(root);

    example.start();
}

document.addEventListener('DOMContentLoaded', main);
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.