Donnerstag, 18 Dezember 2025

Diese Woche am beliebtesten

Vertiefendes Material

Cinematic Snow Engine

Dieses Schnee .js Script erzeugt einen feinen, hochauflösenden und sehr realistischen Schneefall Effekt direkt im Browser. Kein einfacher Overlay Effekt, sondern eine atmosphärische Szene mit Tiefe, Bewegung und Licht. Der Schnee wirkt ruhig, organisch und lebendig zugleich. So wie man ihn aus Filmvorspännen oder hochwertigen Landingpages kennt.

Mehrere Schneeschichten mit unterschiedlichen Größen und Geschwindigkeiten sorgen für räumliche Tiefe. Subtile Windfelder, Mikro-Turbulenzen und leichte Unschärfen lassen jede Flocke individuell und Einzigartig wirken. Nichts wiederholt sich sichtbar, nichts fühlt sich künstlich an.

Wenn Schnee nicht einfach nur „fallen“, sondern Stimmung in Kino Qualität erzeugen soll, ist dieses Script dafür gerade zu perfekt!

Cinematic-snow.js:
(() => {
    const canvas = document.getElementById('snow');
    const ctx = canvas.getContext('2d');

    let W, H, DPR;
    let flakes = [];
    let time = Math.random() * 10000;

    const SETTINGS = {
        layers: [
            { count: 90,  depth: 0.2, size: [0.5, 1.2], speed: 0.25 },
            { count: 140, depth: 0.45, size: [1.0, 2.2], speed: 0.6 },
            { count: 220, depth: 0.75, size: [1.8, 3.5], speed: 1.1 },
            { count: 120, depth: 1.0, size: [2.8, 5.0], speed: 1.6 }
        ]
    };

    function resize() {
        DPR = window.devicePixelRatio || 1;
        W = window.innerWidth;
        H = window.innerHeight;

        canvas.width = W * DPR;
        canvas.height = H * DPR;
        canvas.style.width = W + 'px';
        canvas.style.height = H + 'px';
        ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
    }

    function rand(min, max) {
        return Math.random() * (max - min) + min;
    }

    class Snowflake {
        constructor(layer) {
            this.layer = layer;
            this.reset(true);
        }

        reset(init = false) {
            this.x = Math.random() * W;
            this.y = init ? Math.random() * H : -50;
            this.depth = this.layer.depth * rand(0.7, 1.3);

            this.size = rand(this.layer.size[0], this.layer.size[1]);
            this.speed = this.layer.speed * this.depth;

            this.turbulence = rand(0.6, 1.4);
            this.phase = Math.random() * Math.PI * 2;
            this.spin = rand(-0.015, 0.015);
            this.rotation = Math.random() * Math.PI * 2;

            this.opacity = 0.15 + this.depth * 0.75;
        }

        update(wind, gust) {
            this.phase += 0.008 * this.turbulence;
            this.rotation += this.spin;

            const microDrift = Math.sin(this.phase) * 0.35 * this.depth;
            const fall = this.speed * (1 + gust * 0.6);

            this.x += wind * this.depth + microDrift;
            this.y += fall;

            if (this.y > H + 60 || this.x < -80 || this.x > W + 80) {
                this.reset();
            }
        }

        draw() {
            ctx.save();

            const blur = (1 - this.depth) * 2.2;
            ctx.filter = blur > 0 ? `blur(${blur}px)` : 'none';

            ctx.globalAlpha = this.opacity;
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rotation);

            const g = ctx.createRadialGradient(0, 0, 0, 0, 0, this.size);
            g.addColorStop(0, 'rgba(255,255,255,0.95)');
            g.addColorStop(0.4, 'rgba(255,255,255,0.55)');
            g.addColorStop(1, 'rgba(255,255,255,0)');

            ctx.fillStyle = g;
            ctx.beginPath();
            ctx.arc(0, 0, this.size, 0, Math.PI * 2);
            ctx.fill();

            ctx.restore();
        }
    }

    function build() {
        flakes = [];
        SETTINGS.layers.forEach(layer => {
            for (let i = 0; i < layer.count; i++) {
                flakes.push(new Snowflake(layer));
            }
        });
    }

    function wind(t) {
        return (
            Math.sin(t * 0.00025) * 0.8 +
            Math.sin(t * 0.0006) * 0.35 +
            Math.sin(t * 0.0012) * 0.15
        );
    }

    function gust(t) {
        return Math.max(0, Math.sin(t * 0.00015));
    }

    function vignette() {
        const g = ctx.createRadialGradient(
            W / 2, H / 2, Math.min(W, H) * 0.2,
            W / 2, H / 2, Math.max(W, H) * 0.7
        );
        g.addColorStop(0, 'rgba(0,0,0,0)');
        g.addColorStop(1, 'rgba(0,0,0,0.35)');
        ctx.fillStyle = g;
        ctx.fillRect(0, 0, W, H);
    }

    function frame(t) {
        ctx.clearRect(0, 0, W, H);

        time += 16;
        const w = wind(time);
        const g = gust(time);

        for (const f of flakes) {
            f.update(w, g);
            f.draw();
        }

        vignette();
        requestAnimationFrame(frame);
    }

    window.addEventListener('resize', () => {
        resize();
        build();
    });

    resize();
    build();
    requestAnimationFrame(frame);
})();
Dreamcodes Redaktion
Dreamcodes Redaktion
Jeder auf Dreamcodes bereitgestellte Codeschnipsel sowie jede Tutorial Anleitung basiert auf geprüften Best Practices und fundierter Praxiserfahrung. Ziel ist es, ein belastbares technisches Fundament bereitzustellen und keine unausgereiften oder experimentellen Lösungen zu veröffentlichen. Die konkrete Nutzung, Integration, Anpassung und Absicherung der Inhalte obliegt jedoch dem Anwender. Vor dem produktiven Einsatz sind sämtliche Inhalte eigenverantwortlich zu prüfen, zu testen und gegebenenfalls abzusichern. Dreamcodes stellt die technische Grundlage zur Verfügung, die finale Umsetzung und Verantwortung verbleibt beim Nutzer.
Vorheriges Tutorial

Vielleicht einen Blick WERT?