Skip to content
Snippets Groups Projects
Select Git revision
  • 2bc11fc8ec86b17b4e48680035523c536ffaf226
  • master default protected
2 results

amd64.dockerfile

Blame
  • background_anim.js 8.18 KiB
    // Constants
    const FPS = 60;
    
    const DOTS_NUM_VALUES = [100, 75];
    const INITIAL_VELOCITY_MAX_VALUES = [25, 15];
    const VELOCITY_MAX_VALUES = [40, 30];
    const RADIUS_MIN_VALUES = [2, 0.5];
    const RADIUS_MAX_VALUES = [6, 2];
    const LINE_DISTANCE_MAX_VALUES = [120, 55];
    const LINE_WIDTH_VALUES = [0.2, 0.08];
    const DOT_PUSH_DISTANCE_VALUES = [25, 20];
    
    const DOT_FILL_COLOUR = "#666";
    const DOT_OUTLINE_COLOUR = "#444";
    const LINE_COLOUR = "#777";
    
    const VELOCITY_SLOWDOWN_MULTIPLIER = 0.998;
    const VELOCITY_PUSH_MULTIPLIER = 1.8;
    
    // ----
    
    // Sort-of constants (change with window size)
    let DOTS_NUM = 100;
    
    let INITIAL_VELOCITY_MAX = 25;
    let VELOCITY_MAX = 40;
    let RADIUS_MIN = 1;
    let RADIUS_MAX = 4;
    
    let LINE_DISTANCE_MAX = 150;
    let LINE_WIDTH = 0.2;
    
    let DOT_PUSH_DISTANCE = 25;
    
    class Dot {
        constructor(x, y, radius, vx, vy) {
            this._x = x;
            this._y = y;
            this._radius = radius;
            this._vx = vx;
            this._initial_vx = vx;
            this._vy = vy;
            this._initial_vy = vy;
        }
    
        get x() {
            return this._x;
        }
        set x(value) {
            this._x = value;
        }
        get y() {
            return this._y;
        }
        set y(value) {
            this._y = value;
        }
        get radius() {
            return this._radius;
        }
        set radius(value) {
            this._radius = value;
        }
        get vx() {
            return this._vx;
        }
        set vx(value) {
            this._vx = value;
        }
        get initial_vx() {
            return this._initial_vx
        }
        get vy() {
            return this._vy;
        }
        set vy(value) {
            this._vy = value;
        }
        get initial_vy() {
            return this._initial_vy;
        }
    }
    
    const randInt = (min, max) => {
        return Math.floor(Math.random() * (max - min)) + min;
    };
    
    const distanceBetween = (ax, ay, bx, by) => {
        // Calculate the distance between two points using pythagoras
        // c = sqrt(a^2 + b^2)
        const xSquared = (bx - ax) ** 2;
        const ySquared = (by - ay) ** 2;
        return Math.sqrt(xSquared + ySquared);
    };
    
    const clamp = (number, min, max) => {
        return Math.max(min, Math.min(number, max));
    };
    
    const canvas = document.getElementById("background");
    const ctx = canvas.getContext("2d");
    
    const setDisplayParameters = () => {
        // Set canvas width and height
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
    
        let index = 0;
        if (canvas.width < 768) {
            // Set defaults for lower screen resolutions
            index = 1;
        }
    
        // Set properties
        DOTS_NUM = DOTS_NUM_VALUES[index];
        INITIAL_VELOCITY_MAX = INITIAL_VELOCITY_MAX_VALUES[index];
        VELOCITY_MAX = VELOCITY_MAX_VALUES[index];
        RADIUS_MIN = RADIUS_MIN_VALUES[index];
        RADIUS_MAX = RADIUS_MAX_VALUES[index];
        LINE_DISTANCE_MAX = LINE_DISTANCE_MAX_VALUES[index];
        LINE_WIDTH = LINE_WIDTH_VALUES[index];
        DOT_PUSH_DISTANCE = DOT_PUSH_DISTANCE_VALUES[index];
    };
    
    setDisplayParameters();
    
    let dots = [];
    let mousePos = [0, 0];
    
    for (let i = 0; i < DOTS_NUM; i++) {
        // Append new dot to the array with a random position, radius, and velocity
        dots.push(new Dot(
            Math.random() * canvas.width, // position x
            Math.random() * canvas.height, // position y
            randInt(RADIUS_MIN, RADIUS_MAX), // radius
            randInt(-INITIAL_VELOCITY_MAX, INITIAL_VELOCITY_MAX), // velocity x
            randInt(-INITIAL_VELOCITY_MAX, INITIAL_VELOCITY_MAX) // velocity y
        ));
    }
    
    
    
    const drawDots = () => {
        for (let dot of dots) {
            // Begin the path
            ctx.beginPath();
    
            // Create an arc
            ctx.arc(dot.x, dot.y, dot.radius, 0, 2 * Math.PI, false);
    
            // Fill in the arc
            ctx.fillStyle = DOT_FILL_COLOUR;
            ctx.fill();
    
            // Add an outline
            ctx.fillStyle = DOT_OUTLINE_COLOUR;
            ctx.stroke();
    
            // End the path
            ctx.closePath();
        }
    };
    
    const drawConnectingLines = () => {
        // Draw connecting lines between the dots
        ctx.beginPath();
        for(let dot of dots) {
            // Go to the dot
            ctx.moveTo(dot.x, dot.y);
    
            // Loop through all the dots
            for (let dot2 of dots) {
                if(dot2 !== dot &&
                    distanceBetween(dot.x, dot.y, dot2.x, dot2.y) < LINE_DISTANCE_MAX
                ) {
                    // Draw a line between the dots if the distance is below a threshold
                    ctx.lineTo(dot2.x, dot2.y);
                }
            }
        }
    
        // Draw the lines
        ctx.lineWidth = LINE_WIDTH;
        ctx.strokeStyle = LINE_COLOUR;
        ctx.stroke();
    
        // End the path
        ctx.closePath();
    };
    
    const draw = () => {
        // Clear the screen
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    
        // Set the composite operation
        ctx.globalCompositeOperation = "lighten";
    
        // And now, for the dots
        // Done after lines so lines are below dots
        drawDots();
    
        // Draw connecting lines
        drawConnectingLines();
    };
    
    const physics = () => {
        for (let i = 0; i < dots.length; i++) {
            let dot = dots[i]; // We have to do it this way since we want the dots to update
            // Set positions of dots based on velocity
            dot.x += dot.vx / FPS;
            dot.y += dot.vy / FPS;
    
            // Clamp velocities to maximum
            dot.vx = clamp(dot.vx, -VELOCITY_MAX, VELOCITY_MAX);
            dot.vy = clamp(dot.vy, -VELOCITY_MAX, VELOCITY_MAX);
    
            // Slow down velocity
            dot.vx *= VELOCITY_SLOWDOWN_MULTIPLIER;
            dot.xy *= VELOCITY_SLOWDOWN_MULTIPLIER;
    
            // Stop velocity from going below initial velocity
            if(dot.vx < dot.initial_vx) {
                dot.vx = dot.initial_vx;
            }
            if(dot.vy < dot.initial_vy) {
                dot.vy = dot.initial_vy;
            }
    
            // Invert velocities if off-screen and not already inverted
            if ((dot.x < 0 && dot.vx < 0) || (dot.x > canvas.width && dot.vx > 0)) {
                dot.vx = -dot.vx;
                dot.vx *= VELOCITY_PUSH_MULTIPLIER;
            }
            if ((dot.y < 0 && dot.vy < 0) || (dot.y > canvas.height && dot.vy > 0)) {
                dot.vy = -dot.vy;
                dot.vy *= VELOCITY_PUSH_MULTIPLIER;
            }
    
            // Make dots velocities react to mouse movement (deflected by mouse)
            if (distanceBetween(dot.x, dot.y, mousePos[0], mousePos[1]) < DOT_PUSH_DISTANCE) {
                let ax = mousePos[0];
                let ay = mousePos[1];
                let bx = dot.x;
                let by = dot.y;
                let r = DOT_PUSH_DISTANCE;
    
                let cx = ax + (r * ((bx - ax) / Math.sqrt((bx - ax)**2 + (by - ay)**2)));
                let cy = ay + (r * ((by - ay) / Math.sqrt((bx - ax)**2 + (by - ay)**2)));
    
                dot.vx = -dot.vx;
                dot.vy = -dot.vy;
    
                dot.vx *= VELOCITY_PUSH_MULTIPLIER;
                dot.vy *= VELOCITY_PUSH_MULTIPLIER;
    
                dot.x = cx;
                dot.y = cy;
            }
    
        }
    };
    
    
    let zero = 0;
    
    const tick = (timeStamp) => {
        // Calculate time delta
        // Some browsers use animationframe timers of > 60FPS
        let deltaTime = timeStamp - zero;
    
        // Update if enough time has passed
        if(deltaTime >= (1 / FPS) * 1000) {
            zero = timeStamp;
            draw();
            physics();
        }
    
        // Request the next animation frame
        requestAnimationFrame(tick);
    };
    
    window.addEventListener("mousemove", (event) => {
        // Scale clientX and clientY in case the screen size has changed
        mousePos[0] = (canvas.width / window.innerWidth) * event.clientX;
        mousePos[1] = (canvas.height / window.innerHeight) * event.clientY;
    });
    
    window.addEventListener("resize", () => {
        // Width before resize
        let oldWidth = canvas.width;
        // Height before resize
        let oldHeight = canvas.height;
    
        // Set canvas size and display parameters
        setDisplayParameters();
    
        // Calculate old to new width ratio
        let widthRatio = canvas.width / oldWidth;
        // Calculate old to new height ratio
        let heightRatio = canvas.height / oldHeight;
    
        // Loop through all dots
        for (let i = 0; i < dots.length; i++) {
            let dot = dots[i];
    
            // Reset radius of dots
            dot.radius = randInt(RADIUS_MIN, RADIUS_MAX);
    
            // Reset dots positions outside new window if the window has gotten smaller
            dot.x = dot.x * widthRatio;
            dot.y = dot.y * heightRatio;
        }
    });
    
    document.addEventListener("DOMContentLoaded", () => {
        // Start background animation tick
        requestAnimationFrame(tick);
    });