A browser source overlay for winter vibes for your Live Streams or Videos
1import "./style.css"; 2import { CANVAS_HEIGHT, CANVAS_WIDTH, MAX_PARTICAL_COUNT } from "./config"; 3import { createSnowflake, drawSnowflake, moveSnowflake } from "./snowflake"; 4import { 5 checkCollision, 6 createSnowAccumulator, 7 drawSnowAccumulator, 8} from "./snow_accumulator"; 9 10/** 11 * @type{Array.<Snowflake>} 12 */ 13const snowFlakes = []; 14 15/** 16 * @type SnowAccumulator 17 */ 18const floor = createSnowAccumulator(CANVAS_HEIGHT); 19 20/** 21 * @type {HTMLCanvasElement} 22 */ 23let canvas; 24 25/** 26 * @type {CanvasRenderingContext2D} 27 */ 28let ctx; 29 30let lastSpawn = 0; 31let lastFrame = 0; 32let fps = 0; 33 34window.onload = init; 35 36function init() { 37 // @ts-ignore -- I dunno how to get ts / jsdoc to be ok with this 38 canvas = document.getElementById("main"); 39 40 ctx = canvas.getContext("2d"); 41 canvas.width = CANVAS_WIDTH; 42 canvas.height = CANVAS_HEIGHT; 43 44 window.requestAnimationFrame(gameLoop); 45} 46 47/** 48 * @param time {DOMHighResTimeStamp} 49 */ 50function gameLoop(time) { 51 const delta = time - lastFrame; 52 fps = Math.round(1 / (delta / 1000)); 53 54 ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); 55 if (time - lastSpawn > 500 && snowFlakes.length < MAX_PARTICAL_COUNT) { 56 for (let i = 0; i < Math.floor(Math.random() * 2); i++) { 57 snowFlakes.push(createSnowflake()); 58 } 59 } 60 61 snowFlakes.forEach((flake, idx) => { 62 moveSnowflake(flake, delta); 63 if (checkCollision(floor, flake)) { 64 snowFlakes[idx] = createSnowflake(); 65 } 66 drawSnowflake(flake, ctx); 67 }); 68 69 drawSnowAccumulator(ctx, floor); 70 ctx.fillText("FPS: " + fps, 10, 30); 71 lastFrame = time; 72 window.requestAnimationFrame(gameLoop); 73}