CSS und JS für eine romantische Meteorschauer-Animation

CSS und JS für eine romantische Meteorschauer-Animation

1. Rendern

2. Quellcode

HTML

< Textkörper > 
    <div Klasse = "Container" > 
        <div id = "Maske" > </div > 
        <div id = "Himmel" > </div > 
        <div id = "Mond" > </div> 
        <div id = "Sterne" > </div > 
        <div Klasse = "Wolke Wolke-1" ></div> 
        <div Klasse = "Wolke Wolke-2" > </div > 
        <div Klasse = "Wolke Wolke-3" > </div > 
    </div> 
</ Körper >

CSS

/* - - - - - - Neustart - - - - - - */
 
 * {
     Rand: 0;
     Polsterung: 0;
 }
 
 html,
  Körper {
      Breite: 100 %;
     Mindestbreite: 1000px;
     Höhe: 100 %;
     Mindesthöhe: 400px;
     Überlauf: versteckt;
 }

 /*------------Leinwand------------*/ 
 .container {
      Position: relativ;
     Höhe: 100 %;
 }
 /* Maskenebene */
 
 #Maske {
      Position: absolut;
     Breite: 100 %;
     Höhe: 100 %;
     Hintergrund: rgba(0,0,0,.8);
     Z-Index: 900;
 }
 /*Himmel im Hintergrund*/
 
 #Himmel {
      Breite: 100 %;
     Höhe: 100 %;
     Hintergrund: linearer Farbverlauf (rgba (0,150,255,1), rgba (0,150,255, 0,8), rgba (0,150,255, 0,5));
 }
 / *Mond* /
 
 #Mond {
      Position: absolut;
     oben: 50px;
     Rechts: 200px;
     Breite: 120px;
     Höhe: 120px;
     Hintergrund: rgba(251,255,25,0,938);
     Randradius: 50 %;
     Kastenschatten: 0 0 20px rgba (251, 255, 25, 0,5);
     Z-Index: 9999;
 }
 /* Funkelnde Sterne*/
 
 .blinken {
      Position: absolut;
     Hintergrund: rgb(255,255,255);
     Randradius: 50 %;
     Kastenschatten: 0 0 5px rgb(255,255,255);
     Deckkraft: 0;
     Z-Index: 10000;
 }
 /* Sternschnuppe */
 
 .Stern {
      Position: absolut;
     Deckkraft: 0;
     Z-Index: 10000;
 }
 
 .star :: nach {
      Inhalt: "";
     Anzeige:Block;
     Grenze: fest;
     Rahmenbreite: 2px 0 2px 80px;
     /*Die Länge des Meteors nimmt allmählich ab*/ 
     Rahmenfarbe: transparent transparent transparent rgba(255,255,255,1);
     Rahmenradius: 2px 0 0 2px;
     transformieren: drehen (-45 Grad);
     Transform-Ursprung: 0 0 0;
     Kastenschatten: 0 0 20px rgba(255,255,255,.3);
 }
 / *Wolke* /
 
 .Wolke {
      Position: absolut;
     Breite: 100 %;
     Höhe: 100px;
 }
 
 .cloud-1 {
      unten: -100px;
     Z-Index: 1000;
     Deckkraft: 1;
     transformieren: Maßstab (1,5);
     -webkit-transform: Maßstab(1,5);
     -moz-transform: Skala (1,5);
     -ms-transform:Skala(1,5);
     -o-transform:Skala(1,5);
 }
 
 .cloud-2 {
      links: -100px;
     Unten: -50px;
     Z-Index: 999;
     Deckkraft: . 5 ;
     transformieren: drehen (7 Grad);
     -webkit-transform: drehen (7 Grad);
     -moz-transform: drehen (7 Grad);
     -ms-transform:drehen(7Grad);
     -o-transform:drehen(7Grad);
 }
 
 .cloud-3 {
      links: 120px;
     Unten: -50px;
     Z-Index: 999;
     Deckkraft: . 1 ;
     transformieren: drehen (-10 Grad);
     -webkit-transform: drehen(-10 Grad);
     -moz-transform: drehen(-10 Grad);
     -ms-transform:drehen(-10Grad);
     -o-transform:drehen(-10Grad);
 }
 
 .Kreis {
      Position: absolut;
     Randradius: 50 %;
     Hintergrund: #fff;
 }
 
 .Kreis-1 {
      Breite: 100px;
     Höhe: 100px;
     Oben: -50px;
     Links: 10px;
 }
 
 .Kreis-2 {
      Breite: 150px;
     Höhe: 150px;
     Oben: -50px;
     links: 30px;
 }
 
 .Kreis-3 {
      Breite: 300px;
     Höhe: 300px;
     Oben: -100px;
     Links: 80px;
 }
 
 .Kreis-4 {
      Breite: 200px;
     Höhe: 200px;
     Oben: -60px;
     Links: 300px;
 }
 
 .Kreis-5 {
      Breite: 80px;
     Höhe: 80px;
     Oben: -30px;
     Links: 450px;
 }
 
 .Kreis-6 {
      Breite: 200px;
     Höhe: 200px;
     Oben: -50px;
     Links: 500px;
 }
 
 .Kreis-7 {
      Breite: 100px;
     Höhe: 100px;
     Oben: -10px;
     Links: 650px;
 }
 
 .Kreis-8 {
      Breite: 50px;
     Höhe: 50px;
     oben: 30px;
     Links: 730px;
 }
 
 .Kreis-9 {
      Breite: 100px;
     Höhe: 100px;
     oben: 30px;
     Links: 750px;
 }
 
 .Kreis-10 {
      Breite: 150px;
     Höhe: 150px;
     oben: 10px;
     Links: 800px;
 }
 
 .Kreis-11 {
      Breite: 150px;
     Höhe: 150px;
     Oben: -30px;
     Links: 850px;
 }
 
 .Kreis-12 {
      Breite: 250px;
     Höhe: 250px;
     Oben: -50px;
     Links: 900px;
 }
 
 .Kreis-13 {
      Breite: 200px;
     Höhe: 200px;
     Oben: -40px;
     Links: 1000px;
 }
 
 .Kreis-14 {
      Breite: 300px;
     Höhe: 300px;
     Oben: -70px;
     Links: 1100px;
 }

JS

// Meteoranimation setInterval(function() {
     const obj = addChild("#himmel","div",2,"stern");

    für (lass i = 0; i < obj.children.length; i++) {
         const top = -50 + Math.random() * 200 + "px",
            links = 200 + Math.random() * 1200 + "px",
            Maßstab = 0,3 + Math.random() * 0,5;
        const timer = 1000 + Math.random()*1000;

        obj.children[i].style.top = oben;
        obj.children[i].style.left = links;
        obj.children[i].style.transform = `Skala(${scale})`;

        AnfrageAnimation({
            Element: obj.children[i],
             attr: ["oben", "links", "Deckkraft"],
             Werte: [150, -150, .8],
             Zeit: Timer,
             Flagge: falsch,
             fn: Funktion() {
                AnfrageAnimation({
                    ELE: obj.Kinder[I],
                     attr:["oben","links","undurchsichtig"],
                     Werte: [150, -150, 0],
                     Zeit: Timer,
                     Flagge: falsch,
                     fn:() => {
                        obj.parent.removeChild(obj.children[i]);
                    }
                })
            }
        });
    }

}, 1000);

//Funkelnde Sternanimation setInterval(function() {
     const obj = addChild("#stars","div",2,"blink");

    für (lass i = 0; i < obj.children.length; i++) {
         const top = -50 + Math.random() * 500 + "px",
            links = 200 + Math.random() * 1200 + "px",
            Runde = 1 + Math.random()*2 + "px";
        const Timer = 1000 + Math.random() * 4000;

        obj.children[i].style.top = oben;
        obj.children[i].style.left = links;
        obj.children[i].style.width = rund;
        obj.children[i].style.height = rund;

        AnfrageAnimation({
            Element: obj.children[i],
             attr: "Deckkraft",
             Wert: .5,
             Zeit: Timer,
             Flagge: falsch,
             fn: Funktion() {
                AnfrageAnimation({
                    Element: obj.children[i],
                     attr: "Deckkraft",
                     Wert: 0,
                     Zeit: Timer,
                     Flagge: falsch,
                     fn: Funktion() {
                        obj.parent.removeChild(obj.children[i]);
                    }
                });
            }
        });
    }

}, 1000);

//Mondbewegung requestAnimation ({
    Element: "#Mond",
     attr: "rechts",
     Wert: 1200,
     Zeit: 10000000,
});


//Wolken hinzufügen const clouds = addChild(".cloud","div",14,"circle",true);
für (lass i = 0; i < Wolken.Kinder.Länge; i++) {
     für (sei j = 0; j < Wolken.Kinder[i].Länge;) {
        Wolken.Kinder[i][j].classList.add(`Kreis-${++j}`);
    }
}
//Wolkenanimation let flag = 1;
setInterval()
    Funktion() {
         const clouds = document.querySelectorAll(".cloud");
        const links = Math.random()*5;
        unten = Math.random()*5;

        lass Timer = 0;
        für (lass i = 0; i < Wolken.Länge; i++) {
            AnfrageAnimation({
                ele:Wolken [i],
                 attr: ["links", "unten"],
                 Wert:Flag%2? [-links,-unten]: [links,unten],
                 Zeit: Timer += 500,
                 Flagge: falsch,
                 fn: Funktion() {
                    AnfrageAnimation({
                        ele:Wolken [i],
                         attr: ["links", "unten"],
                         Wert:Flag%2? [links, unten]: [-links, -unten],
                         Zeit: Timer,
                         Flagge: falsch
                    })
                }
            });
        }

        Flagge++;
    }, 2000)

Verpackungsmethode

//------------------------------------------Animation------------------------------------------------------- 
//Bewegungsanimation, rufe Tween.js auf 
//ele: dom | Klasse | ID | Tag Knoten | Klassenname | ID-Name | Tag-Name, unterstützt nur die Auswahl eines Knotens, Klassenname und Tag-Name können nur den ersten auf der Seite auswählen //attr: Attribut Attributname //Wert: Zielwert Zielwert //Zeit: Dauer Dauer //Tween: Zeitfunktion Funktionsgleichung //Flag: Boolescher Wert, der bestimmt, ob nach Wert oder nach Position bewegt wird, standardmäßig wird nach Position bewegt //fn: Rückruf Rückruffunktion // Rückgabewert hinzufügen: gibt das interne Parameterobjekt zurück, Sie können die Animationsfunktion unterbrechen, indem Sie die Eigenschaft „stop“ des Rückgabeobjekts auf „true“ setzen requestAnimation(obj) {
     // -------------------------------------Parametereinstellungen--------------------------------------------- 
    //Standardeigenschaft const parameter = {
         Element: null,
         attr: null,
         Wert: null,
         Zeit: 1000,
         zwischen: "linear",
         Flagge: wahr,
         stop: falsch,
         fn: ""
    }

    //Eingehende Eigenschaften zusammenführen Objekt .assign (Parameter, Objekt); //Doppelte Eigenschaften überschreiben // ------------------------------------- Animationseinstellungen --------- ------------------------------------ 
    //Erstellen Sie Anfangsparameter für die Bewegungsgleichung zur einfachen Wiederverwendung let start = 0; //Dient zum Speichern des anfänglichen Zeitstempels let target = (typeof parameter.ele === "string"? document .querySelector(parameter.ele):parameter.ele), //Zielknoten attr = parameter.attr, //Zielattribut beginAttr = parseFloat(getComputedStyle(target)[attr]), //Attr-Startwert value = parameter.value, //Bewegungszielwert count = value - beginAttr, //Tatsächlicher Bewegungswert time = parameter.time, //Bewegungsdauer,
        tween = Parameter.tween, //Bewegungsfunktionsflag = Parameter.flag,
        callback = parameter.fn, // Rückruffunktion curVal = 0; // aktueller Wert der Bewegung // Bestimmen, ob die übergebene Funktion ein Array ist, Mehrsegmentbewegung (Funktion () {
         wenn (attr Instanz von Array) {
            beginAttr = [];
            Anzahl = [];
            für (hol mein Attribut) {
                 const val = parseFloat(getComputedStyle(Ziel)[i]);
                beginAttr.push(val);
                zählen.push(Wert - Wert);
            }
        }
        if (Wert Instanz von Array) {
             für (sei i im Wert) {
                Anzahl[i] = Wert[i] – beginAttr[i];
            }
        }
    })();

    //Bewegungsfunktion Animation (Zeitstempel) {
         if (parameter.stop) return; //break //anfänglichen Zeitstempel speichern if (!start) start = Zeitstempel;
        // Verstrichene Zeit let t = Zeitstempel - Start;
        //Mehrsegmentbewegung beurteilen if (beginAttr instanceof Array) {
             // const len ​​= beginAttr.length //Länge des Arrays speichern, wiederverwenden //Mehrsegment-Bewegungstyp 1 - mehrere Attribute, gleiches Ziel, gleiche Zeit/unterschiedliche Zeit if (typeof count === "number") { //Gleiches Ziel//gleiche Zeit if (typeof time === "number") {
                     if (t> time) t = time; //Beurteilen, ob der Zielwert überschritten wird //Durchlaufe attr und weise jedem einen Wert zu (lasse i in beginAttr) {
                         if (flag) curVal = Tween [tween] (t, beginAttr [i], count, time); //Tween aufrufen und den aktuellen Attributwert zurückgeben. Die Berechnungsmethode besteht darin, zur Schreibposition zu wechseln else curVal = Tween [tween] (t, beginAttr [i], count + beginAttr [i], time); //Tween aufrufen und den aktuellen Attributwert zurückgeben. Die Berechnungsmethode besteht darin, die Schreibdistanz zu verschieben if (attr [i] === "opacity") target.style [attr [i]] = curVal; //Dem Attribut einen Wert zuweisen else target.style [attr [i]] = curVal + "px" ; //Dem Attribut einen Wert zuweisen if (t < time) requestAnimationFrame (animate); //Beurteilen, ob die Bewegung abgeschlossen ist andere Rückrufe && callback(); //Rückruffunktion aufrufen }
                    zurückkehren;
                }

                //Andere Zeit, wenn (Zeitinstanz des Arrays) {
                     //Schleifenzeit, Attr, bzw. zugewiesen an (lass mich in beginAttr) {
                         //Fehlerbeurteilung if (!time[i] && time[i] !== 0) {
                             neuen Fehler werfen (
                                 „Die Länge der Eingabezeit ist nicht gleich der Länge der Eigenschaft“);
                        }

                        //Beurteilen Sie, ob die Animation abgeschlossen ist. Wenn sie abgeschlossen ist, überspringen Sie diese Schleife, wenn (parseFloat (getComputedStyle (target) [attr [i]]) === (typeof value === "number"? value: value [i]))
                             weitermachen;
                        // t = Zeitstempel - Start; // Initialisiere t bei jedem Schleifendurchgang 
                        if (t > time [i]) t = time [i]; //Beurteilen, ob der Zielwert überschritten wird if (flag || attr [i] === "opacity") curVal = Tween [tween] (t, beginAttr [i], count, i); //Tween aufrufen und den aktuellen Attributwert zurückgeben. Die Berechnungsmethode besteht derzeit darin, zur Schreibposition zu wechseln else curVal = Tween [tween] (t, beginAttr [i], count + beginAttr [i], i); //Tween aufrufen und den aktuellen Attributwert zurückgeben. Die Berechnungsmethode besteht derzeit darin, die Schreibdistanz zu verschieben if (attr [i] === "opacity") target.style [attr [i]] = curVal; //Dem Attribut einen Wert zuweisen else target.style [attr [i]] = curVal + "px" ; //Dem Attribut einen Wert zuweisen }

                    if (t < Math.max(...time)) requestAnimationFrame(animate); //Beurteilen, ob die Funktion die anderen Rückrufe beendet hat && callback(); //Wenn die längste Animation ausgeführt wurde, die Rückruffunktion untersuchen return;
                }
            }

            //Mehrsegment-Bewegungstyp 2 - mehrere Attribute, unterschiedliche Ziele, gleiche Zeit/unterschiedliche Zeit if (Anzahl der Instanzen des Arrays) {
                 //gleiche Zeitwenn (Typ der Zeit === "Zahl") {

                    if (t> time) t = time; //Beurteilen, ob der Zielwert überschritten wird for (let i in beginAttr) { //Schleife attr, count, Werte separat zuweisen //Fehlerbeurteilung if (! count [i] && count [i] !== 0) {
                             neuen Fehler werfen (
                                 „Die Länge des Eingabewertes ist ungleich der Länge der Eigenschaft“);
                        }

                        if (flag || attr[i] === "opacity") curVal = Tween[tween](t, beginAttr[i], count[i], time); //Tween aufrufen und den aktuellen Attributwert zurückgeben. Die Berechnungsmethode besteht darin, zur Schreibposition zu wechseln else curVal = Tween[tween](t, beginAttr[i], count[i] + beginAttr[i], time); //Tween aufrufen und den aktuellen Attributwert zurückgeben. Die Berechnungsmethode besteht darin, die Schreibdistanz zu verschieben if (attr[i] === "opacity") target.style[attr[i]] = curVal; //Dem Attribut einen Wert zuweisen else target.style[attr[i]] = curVal + "px" ; //Dem Attribut einen Wert zuweisen }

                    if (t < Zeit) requestAnimationFrame (animieren); //Beurteilen, ob die Funktion die anderen Rückrufe beendet hat && callback(); //Wenn die längste Animation ausgeführt wurde, die Rückruffunktion untersuchen return;
                }

                //Andere Zeit, wenn (Zeitinstanz des Arrays) {
                     für (lass i in beginAttr) {
                         //Fehlerbeurteilung if (!time[i] && time[i] !== 0) {
                             neuen Fehler werfen (
                                 „Die Länge der Eingabezeit) ist nicht gleich der Länge der Eigenschaft“);
                        }

                        //Beurteilen Sie, ob die Animation abgeschlossen ist. Wenn sie abgeschlossen ist, überspringen Sie diese Schleife, wenn (parseFloat (getComputedStyle (target) [attr [i]]) === (typeof value === "number"? value: value [i]))
                             weitermachen;

                        if (t> time[i]) t = time[i]; //Beurteilen, ob der Zielwert überschritten wird //Fehlerbeurteilung if (! count[i] && count[i] !== 0) {
                             neuen Fehler werfen (
                                 „Die Länge des Eingabewertes ist ungleich der Länge der Eigenschaft“);
                        }

                        if (flag || attr[i] === "opacity") curVal = Tween[tween](t, beginAttr[i], count[i], time[i]); //Tween aufrufen und den aktuellen Attributwert zurückgeben. Die Berechnungsmethode besteht darin, zur geschriebenen Position zu wechseln else curVal = Tween[tween](t, beginAttr[i], count[i] + beginAttr[i], time[i]); //Tween aufrufen und den aktuellen Attributwert zurückgeben. Die Berechnungsmethode besteht darin, die geschriebene Distanz zu verschieben if (attr[i] === "opacity") target.style[attr[i]] = curVal;
                        Andernfalls target.style[attr[i]] = curVal + "px";
                    }

                    wenn (t < Math.max(... Zeit)) requestAnimationFrame(animieren);
                    sonst Rückruf und Rückruf();
                    zurückkehren;
                }
            }

        }

        //Einzelbewegungsmodus wenn (t> Zeit) t = Zeit;
        if (flag || attr === "opacity") curVal = Tween [tween] (t, beginAttr, count, time); //Tween aufrufen und den aktuellen Attributwert zurückgeben. Die Berechnungsmethode besteht darin, zur Schreibposition zu wechseln else curVal = Tween [tween] (t, beginAttr [i], count + beginAttr, time); //Tween aufrufen und den aktuellen Attributwert zurückgeben. Die Berechnungsmethode besteht darin, die Schreibdistanz zu verschieben if (attr === "opacity") target.style [attr] = curVal;
        Andernfalls target.style[attr] = curVal + "px";

        wenn (t < Zeit) requestAnimationFrame(animieren);
        sonst Rückruf und Rückruf();

    }

    requestAnimationFrame(animation);
    Rückgabeparameter; //Objekt für Unterbrechung oder andere Zwecke zurückgeben}
//Tween.js 
/ *
 * t: verstrichene Zeit * b: Startwert * c: Gesamtbewegungswert * d: Dauer *
 *Gleichung der Kurve*
 * http://www.cnblogs.com/bluedream2009/archive/2010/06/19/1760909.html
 * * /

Sei Tween = {
     linear: Funktion (t, b, c, d) { // gleichmäßige Geschwindigkeit gibt c * t / d + b zurück;
    },
    easeIn: Funktion (t, b, c, d) { // Beschleunigungskurve return c * (t /= d) * t + b;
    },
    easeOut: Funktion (t, b, c, d) { // Verzögerungskurve return -c * (t /= d) * (t - 2) + b;
    },
    easeBoth: Funktion (t, b, c, d) { // Beschleunigungs- und Verzögerungskurve wenn ((t / = d / 2) < 1) {
             Rückgabewert c / 2 * t * t + b;
        }
        Rückgabewert -c/2*((-t)*(t-2)-1)+b;
    },
    easeInStrong: Funktion (t, b, c, d) { // Beschleunigungskurve return c * (t /= d) * t * t * t + b;
    },
    easeOutStrong: Funktion (t, b, c, d) { // easeOut-Kurve return -c * ((t = t / d – 1) * t * t * t – 1) + b;
    },
    easeBothStrong: function (t, b, c, d) { //Beschleunigungs- und Verzögerungslinie if ((t / = d / 2) < 1) {
             Rückgabe c / 2 * t * t * t * t + b;
        }
        Rückgabewert -c/2*((t-=2)*t*t*t-2)+b;
    },
    elasticIn: Funktion (t, b, c, d, a, p) { // Sinus-Dämpfungskurve (elastisch in allmählich)
        wenn (t === 0) {
             Rückkehr b;
        }
        wenn ((t /= d) == 1) {
             gebe b + c zurück;
        }
        wenn (!p) {
            p = d * 0,3;
        }
        wenn (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } anders {
             var s = p / (2 * Math.PI) * Math.asin(c/a);
        }
        Rückgabe - (A * math.pow(2, 10 * (T - = 1)) * math.sin((T * d - S) * (2 * math.PI) / P)) + B;
    },
    elasticOut: Funktion (t, b, c, d, a, p) { // Sinusverstärkungskurve (elastischer Ausgang)
        wenn (t === 0) {
             Rückkehr b;
        }
        wenn ((t /= d) == 1) {
             gebe b + c zurück;
        }
        wenn (!p) {
            p = d * 0,3;
        }
        wenn (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } anders {
             var s = p / (2 * Math.PI) * Math.asin(c/a);
        }
        gibt a * Math.pow(2, -10*t) * Math.sin((t*d - s) * (2*Math.PI) / p) + c + b zurück;
    },
    elasticBoth: Funktion(t, b, c, d, a, p) {
         wenn (t === 0) {
             Rückkehr b;
        }
        wenn ((t/=d/2) == 2) {
             gebe b + c zurück;
        }
        wenn (!p) {
            p = d * (0,3 * 1,5);
        }
        wenn (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } anders {
             var s = p / (2 * Math.PI) * Math.asin(c/a);
        }
        wenn (T < 1) {
             Gibt -0,5 * (A * math.pow(2, 10 * (T - = 1)) * zurück.
                 math.sin((T * d - S) * (2 * math.PI) / p)) + b;
        }
        Gibt ein * Math.pow(2, -10 * (t - = 1)) * zurück.
             Math.sin((t*d - s)*(2*Math.PI)/p)*0,5+c+b;
    },
    backIn: Funktion (t, b, c, d, s) { // Rückwärtsbeschleunigung (allmählicher Rückwärtseintritt)
        wenn (Typ von s == 'undefiniert') {
            s = 1,70158;
        }
        Rückgabewert c*(t/=d)*t*((s+1)*t-s)+b;
    },
    backOut: Funktion (t, b, c, d, s) {
         wenn (Typ von s == 'undefiniert') {
            s = 3,70158; //Rückzugsdistanz}
        gibt c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b zurück;
    },
    zurückBoth: Funktion(t, b, c, d, s) {
         wenn (Typ von s == 'undefiniert') {
            s = 1,70158;
        }
        wenn ((t/=d/2) < 1) {
             Rückgabewert c/2*(t*t*(((s*=(1,525))+1)*t-s))+b;
        }
        Rückgabewert c/2*((t-=2)*t*(((s*=(1,525))+1)*t+s)+2)+b;
    },
    bounceIn: function (t, b, c, d) { // Der Ball wird allmählich ausgeblendet)
        gibt c - Tween['bounceOut'](d - t, 0, c, d) + b zurück;
    },
    bounceOut: Funktion(t, b, c, d) {
         wenn ((t/=d) < (1/2,75)) {
             gebe c * (7,5625 * t * t) + b zurück;
        } sonst wenn (t < (2/2,75)) {
             Rückgabewert c*(7,5625*(t - =(1,5/2,75))*t+0,75)+b;
        } sonst wenn (t < (2,5 / 2,75)) {
             Rückgabewert c*(7,5625*(t - =(2,25/2,75))*t+0,9375)+b;
        }
        Rückgabewert c*(7,5625*(t - =(2,625/2,75))*t+0,984375)+b;
    },
    bounceBoth: Funktion(T, B, C, D) {
         wenn (T < d / 2) {
             gibt tween['bounceIn'](T*2, 0, C, D)*0,5 + B zurück;
        }
        zurück Tween['bounceOut'](t*2-d,0,c,d)*0,5+c*0,5+b;
    }
}


// ------------------------------------------- DOM-Operationen --- ------------------------------------------------ 
//Knoten hinzufügen//Element: übergeordneter Knoten, unterstützt Eingabevariablen, ID-Werte, Klassenwerte und Beschriftungswerte. Mit Ausnahme von Variablen müssen andere Werte Zeichenfolgen sein. // Knoten: Bezeichnungsname hinzugefügt, Wert ist eine Zeichenfolge. // n: Anzahl der hinzugefügten Knoten. // Klassenname: An den Knoten gebundener Klassenname, Wert ist eine Zeichenfolge, mehrere Klassennamen sind durch Leerzeichen getrennt. // Boolesch: ob alle übergeordneten Zielknoten ausgewählt werden sollen. Optionaler Parameter. Wenn er nicht eingegeben wird, wird er als falsch gewertet und nur der erste ausgewählte Knoten wird abgeglichen. Funktion addChild (ele, node, n, className, boolean) {
     //Knoten abrufen let parent = null;

    wenn (Typ des Elements !== "Zeichenfolge") übergeordnetes Element = Element;
    sonst wenn (ele[0] === "#") übergeordnetes Element = document.getElementById(ele.slice(1));
    sonst wenn (ele[0] === ".") {
         wenn (boolean === false) übergeordnetes Element = document.getElementsByClassName(ele.slice(1))[0];
        sonst übergeordnetes Element = document.getElementsByClassName(ele.slice(1));
    } anders {
         wenn (boolean === false) übergeordnetes Element = docuemnt.getElementsByTagName(ele)[0];
        sonst übergeordnetes Element = document.getElementsByTagNameNS(ele);
    }

    //Deklariere Objekte, die zum Speichern von übergeordneten und untergeordneten Knoten verwendet werden const obj = {
         "Elternteil": Elternteil,
         "Kinder": []
    };

    //Knoten hinzufügen, wenn (boolean) {
         für (lass i = 0; i < übergeordnete Länge; i++) {
             //Containerfragment erstellen const fragment = document.createDocumentFragment();
            //Untergeordnete Knoten für Rückgabewert speichern obj.children[i] = [];

            für (sei j = 0; j < n; j++) {
                 const target = document.createElement(Knoten);
                ziel.klassenname = klassenname;
                fragment.appendChild(Ziel);
                //Untergeordnete Knoten zum Array hinzufügen, um den Rückgabewert zu erhalten obj.children[i][j] = target;
            }

            Übergeordnet[I].anhängenKind(Fragment)
        }
    } anders {
         //Fragmentcontainer erstellen const fragment = document.createDocumentFragment();

        für (sei i = 0; i < n; i++) {
             const target = document.createElement(Knoten);
            ziel.klassenname = klassenname;
            fragment.appendChild(Ziel);
            //Unterknoten für Rückgabewert hinzufügen obj.children[i] = target;
        }
        //Den Fragmentcontainer auf einmal dem übergeordneten Knoten hinzufügen parent.appendChild(fragment);
    }

    //Rückgabeparameter für die aufzurufende Animationsfunktion return obj;
}

3. Fallanalyse

HTML

Da es viele Knoten gibt und ich es so realistisch und interessant wie möglich gestalten möchte, habe ich den Knoten auch zufällige Positionen hinzugefügt. Daher wird die Ausgabe der Knoten von JS gesteuert. In HTML werden nur einige übergeordnete Elementfelder sowie die entsprechenden ID-Namen und Klassennamen geschrieben, und die Struktur ist relativ einfach.

CSS

Die Schwierigkeit des CSS-Teils liegt im Stil der Meteore und im Zeichnen der Wolken mit Kreisen und dem anschließenden Stapeln der Wolken, um einen dreidimensionalen Effekt zu erzeugen.

Lassen Sie uns zunächst über den Meteor-Stil sprechen:

#Himmel .Stern {
      Position: absolut;
     Deckkraft: 0;
     Z-Index: 10000;
 }
 
 .star :: nach {
      Inhalt: "";
     Anzeige:Block;
     Grenze: fest;
     Rahmenbreite: 2px 0 2px 80px;
     /*Die Länge des Meteors nimmt allmählich ab*/ 
     Rahmenfarbe: transparent transparent transparent rgba(255,255,255,1);
     Rahmenradius: 2px 0 0 2px;
     transformieren: drehen (-45 Grad);
     Transform-Ursprung: 0 0 0;
     Kastenschatten: 0 0 20px rgba(255,255,255,.3);
 }

Extrahieren Sie zunächst den gemeinsamen Stil und fügen Sie Positionierungsattribute hinzu.

Fügen Sie anschließend mit der Pseudoklasse „after“ eine Sternschnuppe nach dem Stern hinzu und zeichnen Sie diese mit dem Attribut „border“:

1) Modellzeichnung: Die Reihenfolge der Rahmenbreite ist oben, rechts, unten, links auf den vier Seiten. Ebenso ist die Reihenfolge der Rahmenfarbe oben, rechts, unten, links auf den vier Seiten. Auf diese Weise können Sie, nachdem Sie die Rahmenbreite und die Rahmenfarbe nacheinander angepasst haben, sehen, dass 2 Pixel die Breite des Meteors, 80 Pixel die Länge des Meteors und 0 Pixel der Schweif des Meteors sind. Somit entsteht ein … Ein Shooting-Star-Modell mit einer Kopfbreite von 2px, einem Schwanz von 0px und einer Länge von 80px;

2) Etwas realistischer: über den Randradius? Fügen Sie dem Kopf des Meteors abgerundete Ecken hinzu, damit er realistischer aussieht, und drehen Sie ihn schließlich mithilfe von Roteta in einem Winkel, damit es aussieht, als würde er herunterfallen.

3) Funkeln hinzufügen: Verwenden Sie Kastenschatten, um der Sternschnuppe einen kleinen Heiligenschein hinzuzufügen, damit es aussieht, als hätte sie einen funkelnden Effekt;

Nach den oben genannten 3 Schritten wird eine Sternschnuppe gezeichnet.

Dann die Wolken:

Da der Cloud-Code relativ lang ist, werde ich ihn hier nicht veröffentlichen. Die Methode besteht lediglich darin, Kreise nacheinander überlappen zu lassen, um die Form einer Wolke zu vervollständigen.
Nachdem Sie eine Wolkenebene fertiggestellt haben, kopieren Sie sie und verwenden Sie dann Drehung, Deckkraft, Linkspositionierung usw., um einen verblassenden und überlappenden 3D-Effekt für mehrere Wolkenebenen zu erzeugen.

JS

Der JS-Teil verwendet Meteor als Beispiel

setzeIntervall(Funktion() {
     const obj = addChild("#sky","div",2,"star"); //Sternschnuppe einfügen for(let i = 0; i < obj.children.length; i++) {
         //zufällige Position const top = -50 + Math.random() * 200 + "px",
            links = 200 + Math.random() * 1200 + "px",
            Maßstab = 0,3 + Math.random() * 0,5;
        const timer = 1000 + Math.random()*1000;

        obj.children[i].style.top = oben;
        obj.children[i].style.left = links;
        obj.children[i].style.transform = `Skala(${scale})`;
        
        //Animation hinzufügen requestAnimation({
            Element: obj.children[i],
             attr: ["oben", "links", "Deckkraft"],
             Werte: [150, -150, .8],
             Zeit: Timer,
             Flagge: falsch,
             fn: Funktion() {
                AnfrageAnimation({
                    ELE: obj.Kinder[I],
                     attr:["oben","links","undurchsichtig"],
                     Werte: [150, -150, 0],
                     Zeit: Timer,
                     Flagge: falsch,
                     fn:() => {
                        obj.parent.removeChild(obj.children[I]); //Knoten am Ende der Animation löschen}
                })
            }
        });
    }

}, 1000);

Hier werden zwei Methoden verwendet, die ich selbst gekapselt habe, eine ist requestAnimation basierend auf requestAnimationFrame und die andere ist addChild basierend auf appendChild.

Um den Effekt zufälliger Sternpositionen zu erzielen, werden Meteore kontinuierlich über den Timer setInterval eingefügt und gelöscht:

Zunächst werden der Seite jedes Mal 2 Meteore hinzugefügt, wobei das Timerintervall jedoch kürzer ist als die Animationszeit des Meteors. Dadurch wird sichergestellt, dass die Anzahl der Meteore auf der Seite kein fester Wert ist, sondern definitiv größer als 2 ist. Sonst kämen zwei Meteore auf einmal etwas zu kurz;

Weisen Sie dann über eine Schleife (Sie können z. B. auch die Formel „for“ verwenden, was auch immer funktioniert. Für die einfachste Variante) jedem neuen Meteor, der der Seite hinzugefügt wird, eine zufällige Position (oben links), eine zufällige Größe (Skala) und eine zufällige Ausführungszeit der Animation (Timer) zu.

Abschließend animieren wir in der Schleife jeden neuen Meteor, der der Seite hinzugefügt wird, und löschen den Knoten nach Abschluss der Animation über die Rückruffunktion. Hierbei ist zu beachten, dass die Animation in zwei Phasen (Erscheinen und Verschwinden, hauptsächlich Opazitätskontrolle) unterteilt werden sollte. Außerdem bewegt sich bei meiner Verarbeitung hier jeder Meteor um die gleiche Distanz von 300 Pixeln. Ich denke, diese Distanz kann auch durch Zufallszahlen gesteuert werden, aber ich war faul und habe es nicht getan.

4. Kleine Probleme

Ich habe bisher zwei Probleme gefunden:

Ein Problem ist der DOM-Betrieb selbst. Die Seite fügt ständig Knoten hinzu und löscht sie, was zu ständigen Reflow und Neuzeichnen verbrauchen viel Leistung;

Das zweite ist das Problem des requestAnimationFrame selbst. Denn der Timer fügt ständig Knoten hinzu und die Funktion von requestAnimationFrame besteht darin, dass die Animation angehalten wird, wenn Sie die aktuelle Seite verlassen, um andere Seiten zu durchsuchen. Dies führt zu einem Problem. Es werden ständig Knoten hinzugefügt, aber die Animationen werden alle angehalten und nicht ausgeführt. Wenn Sie also das nächste Mal auf diese Seite zurückkehren, wird die Animation explodieren und Sie werden sehen, wie der Bildschirm einfriert und viele Kaulquappen gemeinsam losziehen, um ihre Mutter zu finden.

5. Fazit

Obwohl dieser kleine Fall vom Schwierigkeitsgrad her einfach ist, ist er hochgradig skalierbar – beispielsweise kann das Ausdrücken von Liebe, das Bekunden von Liebe, das Romantischsein usw. auch mit reinem CSS erreicht werden.

Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, er wird für jedermanns Studium hilfreich sein. Ich hoffe auch, dass jeder 123WORDPRESS.COM unterstützen wird.

<<:  So betreiben Sie eine MySql-Datenbank mit Gorm

>>:  So verbessern Sie die Startgeschwindigkeit von Idea und beheben Probleme mit verstümmelten Zeichen im Tomcat-Protokoll

Artikel empfehlen

Was tun, wenn Sie Ihr Passwort in MySQL 5.7.17 vergessen?

1. Skip-Grant-Tables zur Datei my.ini hinzufügen ...

So verstehen Sie die semantische HTML-Struktur

Ich glaube, jeder kennt HTML und CSS, kennt die T...

Eine kurze Analyse der Unterschiede zwischen Undo, Redo und Binlog in MySQL

Inhaltsverzeichnis Vorwort 【Protokoll rückgängig ...

Springboot+VUE zur Realisierung von Anmeldung und Registrierung

In diesem Artikelbeispiel wird der spezifische Co...

Die am häufigsten verwendeten HTML-Tags zum Erstellen von Webseiten

1. Optimierung häufig verwendeter HTML-Tags HTML ...

Ein Artikel, der Ihnen hilft, jQuery-Animationen zu verstehen

Inhaltsverzeichnis 1. Steuern Sie die Anzeige und...

Verwendung von TypeScript-Generics

Inhaltsverzeichnis 1. Einfach zu bedienen 2. Verw...

Installationsprozess von CentOS8 Linux 8.0.1905 (Abbildung)

Die aktuellste Version von CentOS ist CentOS 8. A...

Die Verknüpfungsmethode zwischen Menü und Registerkarte von vue+iview

Vue+iview-Menü und Tab-Verknüpfung Ich entwickle ...