Site Search:

How to overlap text above animation

Back>

You can overlap text div above the moving partial animations. The following example use HTML 5 canvas to achieve the animation.

Here is the example:

Example

<h2>
Binary Search Tree (BST)</h2>
<div>
            <canvas id="canvas" width=800 height=600></canvas>
        </div>
        <div id="buttons">
            <button id="explosion">size(), get() and put()</button>
            <button id="fallout">min(), floor(), select() and rank()</button>
            <button id="spin">deletMin() and delet()</button>
            <button id="amoeba">print() and keys()</button>
            <div id="colors">
                <div class="red box"></div>
                <div class="green box"></div>
                <div class="blue box"></div>
            </div>
            <button style="display: none;">Number of particles:<br><i id="particles">0</i></button>
            <input style="display: none;" type="range" min="1" max="10000" value="1000" id="slider">       
         
        </div>
<style>
#menu {
    color: olive;
    text-align: center;
    margin-bottom: 0;
    padding-bottom: 0;
    line-height: 1em;
    font-weight: bold;
}
body {
    display: flex;
    flex-direction: row;
}

#buttons {
    margin: 10px;
    /* padding: 10px; */
    display: flex;
    flex-direction: column;
}
#colors {
    margin: 10px;
    /* padding: 10px; */
    display: flex;
    flex-direction: row;
    justify-content: space-evenly;
    /* background: grey; */
}

.box {
    width: 20px;
    height: 20px;
}
.red {
    background: red;
}
.green {
    background: green;
}

.blue {
    background: blue;
}
</style>

<script>
class PixelManipulation {
    constructor(canvas) {
        this.context = canvas.getContext("2d");
        this.width = canvas.width;
        this.height = canvas.height;
        this.image = this.context.getImageData(0, 0, this.width, this.height);
    }
    getImage() {
        this.image = this.context.getImageData(0, 0, this.width, this.height);
    }
    setImage() {
        this.context.putImageData(this.image, 0, 0);
    }

    setPixel(x, y, red, green, blue) {
        const pixelIndex = (y * this.width + x) * 4;
        this.image.data[pixelIndex] = red;
        this.image.data[pixelIndex + 1] = green;
        this.image.data[pixelIndex + 2] = blue;

    }
    fillColor(red, green, blue, alpha = 255) {
        for (let i = 0; i < this.width * this.height * 4; i+=4) {
            this.image.data[i] = red;
            this.image.data[i + 1] = green;
            this.image.data[i + 2] = blue;
            this.image.data[i + 3] = alpha;
        }   
    }
    fillText(choice) {
       this.context.font = "30px Arial";
       //this.context.fillStyle = "#ff0000";
       this.context.fillStyle = "#ffea00";
       this.context.fillText(choice,10,50);
    }
}

class Particle {
    constructor() {
        this.x;
        this.y;
        this.direction;
        this.speed;
        this.init;
        this.update;
    }
}

class Swarm {
    constructor(canvas, amount = 10000, color = 1) {
        this.size = amount;
        this.particles = [];
        this.pixels = new PixelManipulation(canvas);
        this.color = color;
        this.style = this.initSpin;
        this.update = this.updateSpin;
        this.code = 'great code you are writing';
    }

    setPattern(pattern) {
     
        switch(pattern) {
            case "fallout": {
                this.style = this.initFallout;
                this.update = this.updateFallout;
                this.code = 'code 1';
                break;
            }
            case "spin": {
                this.style = this.initSpin;
                this.update = this.updateSpin;
                this.code = 'code 2';
                break;
            }
            case "amoeba": {
                this.style = this.initAmoeba;
                this.update = this.updateAmoeba;
                this.code = 'code 3';
                break;
            }
            case "explosion": {
                this.style = this.initExplosion;
                this.update = this.updateExplosion;
                this.code = 'code 4';
                break;
            }
        }
        this.init();
    };

    setColor(color) {
        switch(color) {
            case 0: {             
                this.code = 'text 1';
                break;
            }
            case 1: {             
                this.code = 'text 2';
                break;
            }
            case 2: {             
                this.code = 'text 3';
                break;
            }         
        }
        this.color = color;
    };
    setParticles(value) {
        this.size = value;
        this.init();
    }
    init() {
        ; // 0 = red, 1 = green, 2 = blue
     
        this.particles = [];
        for(let i = 0; i < this.size; i++) {
            this.particles.push(new Particle);
            // this.particles[i].update = this.particles[i].updateSpin;
            this.particles[i].update = this.update;
            this.particles[i].init = this.style;
            this.particles[i].init();
        } 
         
        this.pixels.fillColor(0, 0, 0);
        this.pixels.setImage();
        this.pixels.fillText(this.code);
     
    }

    initFallout() {
        this.direction = 2 * Math.PI * Math.random();
        this.speed = 0.02 * Math.random();
        this.x = 0;
        this.y = 0;
        // this.update = this.updateFallout;
    }
    updateFallout(delta) {
        const xspeed = this.speed * Math.cos(this.direction);
        const yspeed = this.speed * Math.sin(this.direction);

        this.x += xspeed * delta;
        this.y += yspeed * delta;
        if(this.x <= -1.0 || this.x >= 1.0 || this.y <= -1.0 || this.y >= 1.0) {
            this.x = -1.10;
            this.y = -1.10
        }
    }

    initExplosion() {
        this.direction = 2 * Math.PI * Math.random();
        this.speed = 0.02 * Math.random();
        this.x = 0;
        this.y = 0;
        this.speed *= this.speed/2;
        // this.update = this.updateExplosion;
    }
    updateExplosion(delta) {
        const xspeed = this.speed * Math.cos(this.direction);
        const yspeed = this.speed * Math.sin(this.direction);

        this.x += xspeed * delta;
        this.y += yspeed * delta;
        if(this.x <= -1.0 || this.x >= 1.0 || this.y <= -1.0 || this.y >= 1.0) {
            // this.init();
            this.x = -1.10;
            this.y = -1.10
        }
    }
    initSpin() {
        this.direction = 2 * Math.PI * Math.random();
        this.speed = 0.02 * Math.random();
        this.x = 0;
        this.y = 0;
        this.speed *= this.speed/2;
        // this.update = this.updateSpin;
    }
    updateSpin(delta) {
        this.direction += 0.01;
        const xspeed = this.speed * Math.cos(this.direction);
        const yspeed = this.speed * Math.sin(this.direction);

        this.x += xspeed * delta;
        this.y += yspeed * delta;
        if(this.x <= -1.0 || this.x >= 1.0 || this.y <= -1.0 || this.y >= 1.0) {
            // this.init();
            this.x = -1.10;
            this.y = -1.10
        }
    }

    initAmoeba() {
        this.direction = 2 * Math.PI * Math.random();
        this.speed = 0.02 * Math.random();
        this.x = 0;
        this.y = 0;
        this.speed *= this.speed/2;
        // this.update = this.updateAmoeba;
    }
    updateAmoeba(delta) {
        this.direction += Math.random();;
        const xspeed = this.speed * Math.cos(this.direction);
        const yspeed = this.speed * Math.sin(this.direction);

        this.x += xspeed * delta;
        this.y += yspeed * delta;
        if(this.x <= -1.0 || this.x >= 1.0 || this.y <= -1.0 || this.y >= 1.0) {
            // this.init();
            this.x = -1.10;
            this.y = -1.10
        }
    }

    render(delta) {
        const width = 800;
        const height = 600;

        const oldPixels = this.pixels.context.getImageData(0, 0, width, height).data;
        for(let y=0; y<height; y++) {
            for(let x = 0; x<width; x++) {

                let redTotal = 0;

                for(let row = -1; row <=1; row++) {
                    for(let col = -1; col <=1; col++) {
                        let currentX = x + col;
                        let currentY = y + row;

                        if(currentX >= 0 && currentX < width && currentY >= 0 && currentY < height) {
                            let red = oldPixels[4*(currentY * width + currentX) + this.color]                         
                            redTotal += red;
                        }
                    }
                }
                this.pixels.image.data[4*(y * width + x) + this.color] = redTotal / 9;
            }
        }

        for(let i = 0; i < this.size; i++) {
            const p = this.particles[i];
            p.update(delta);
            const xPos = Math.floor((1 + p.x) * width/2);
            const yPos = Math.floor(p.y * width/2 + height/2);
            this.pixels.image.data[4 * (yPos * width + xPos) + this.color] = 255;
        }
     
        this.pixels.setImage();
        this.pixels.fillText(this.code);
     
    }
}

const fallout = document.querySelector("#fallout");
const explosion = document.querySelector("#explosion");
const spin = document.querySelector("#spin");
const amoeba = document.querySelector("#amoeba");
const red = document.querySelector(".red");
const green = document.querySelector(".green");
const blue = document.querySelector(".blue");
const particles = document.querySelector("#particles");
const slider = document.querySelector("#slider");

fallout.addEventListener("click", () => swarm.setPattern("fallout"));
explosion.addEventListener("click", () => swarm.setPattern("explosion"));
amoeba.addEventListener("click", () => swarm.setPattern("amoeba"));
spin.addEventListener("click", () => swarm.setPattern("spin"));

slider.addEventListener("input", () => {
    particles.innerHTML = slider.value;
});
slider.addEventListener("mouseup", () => {
    swarm.setParticles(slider.value);
});

red.addEventListener("click", () => swarm.setColor(0));
green.addEventListener("click", () => swarm.setColor(1));
blue.addEventListener("click", () => swarm.setColor(2));



// start
slider.value = 2000;
particles.innerHTML = slider.value;
let currentTime = Date.now();
let previousTime = Date.now();
let deltaTime = 0;

const swarm = new Swarm(canvas, slider.value);
swarm.init();

setInterval(() => {
    currentTime = Date.now();
    swarm.render(deltaTime);
    deltaTime = currentTime - previousTime;
    previousTime = currentTime;
}, 1000/48);

</script>