html5、烟花、流星

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>流星、烟花</title>
    <style>
        body {
            background: #000;
            margin: 0;
        }

        canvas {
            cursor: pointer;
            display: block;
        }

        .moon {
            position: fixed;
            right: 10%;
            top: 10%;
            width: 9rem;
            height: 9rem;
            overflow: hidden;
            border-radius: 50%;
            box-shadow: 0 0 10px #fff, 0 0 30px #fff;
        }

        .moon>img {
            width: 100%;
            transform: scale(1.5);
            margin-left: -2px;
        }

        .verse {
            position: fixed;
            right: 5%;
            top: 30%;
            /* width: 30%; */
            text-align: center;
            letter-spacing: 2px;
            color: rgb(228, 215, 241);
            font-family: 楷体;
            font-weight: bold;
            /* text-shadow: 0px 0px 1px #fff; */
        }

        .path-0 {
            animation: pathAnim-0 4s;
            animation-timing-function: linear;
            animation-iteration-count: infinite;
        }

        @keyframes pathAnim-0 {
            0% {
                d: path("M 0,400 C 0,400 0,80 0,80 C 56.809462444771725,71.1209499263623 113.61892488954345,62.2418998527246 169,64 C 224.38107511045655,65.7581001472754 278.3337628865979,78.15335051546391 337,81 C 395.6662371134021,83.84664948453609 459.04602356406485,77.14469808541973 517,82 C 574.9539764359351,86.85530191458027 627.4821428571429,103.26785714285714 701,102 C 774.5178571428571,100.73214285714286 869.0254050073638,81.78387334315168 932,73 C 994.9745949926362,64.21612665684832 1026.416237113402,65.59664948453609 1082,73 C 1137.583762886598,80.40335051546391 1217.309646539028,93.82952871870398 1281,96 C 1344.690353460972,98.17047128129602 1392.345176730486,89.08523564064801 1440,80 C 1440,80 1440,400 1440,400 Z");
            }

            25% {
                d: path("M 0,400 C 0,400 0,80 0,80 C 51.83302650957289,81.79418262150222 103.66605301914578,83.58836524300442 167,76 C 230.33394698085422,68.41163475699558 305.16881443298973,51.44072164948453 365,57 C 424.83118556701027,62.55927835051547 469.6586892488955,90.64874815905745 532,105 C 594.3413107511045,119.35125184094255 674.1964285714286,119.96428571428571 734,108 C 793.8035714285714,96.03571428571429 833.5555964653902,71.4941089837997 886,75 C 938.4444035346098,78.5058910162003 1003.5811855670104,110.05927835051546 1060,107 C 1116.4188144329896,103.94072164948454 1164.1196612665685,66.26877761413844 1226,56 C 1287.8803387334315,45.73122238586156 1363.9401693667157,62.86561119293078 1440,80 C 1440,80 1440,400 1440,400 Z");
            }

            50% {
                d: path("M 0,400 C 0,400 0,80 0,80 C 52.520066273932244,72.68317378497791 105.04013254786449,65.36634756995582 171,69 C 236.9598674521355,72.63365243004418 316.3595360824742,87.21778350515464 384,92 C 451.6404639175258,96.78221649484536 507.52172312223854,91.76251840942562 551,93 C 594.4782768777615,94.23748159057438 625.5535714285713,101.73214285714286 693,104 C 760.4464285714287,106.26785714285714 864.2639911634759,103.30891016200296 927,103 C 989.7360088365241,102.69108983799704 1011.3904639175257,105.03221649484536 1065,94 C 1118.6095360824743,82.96778350515464 1204.1741531664213,58.56222385861561 1272,54 C 1339.8258468335787,49.43777614138439 1389.9129234167895,64.7188880706922 1440,80 C 1440,80 1440,400 1440,400 Z");
            }

            75% {
                d: path("M 0,400 C 0,400 0,80 0,80 C 63.355486008836536,92.28865979381443 126.71097201767307,104.57731958762886 182,102 C 237.28902798232693,99.42268041237114 284.5115979381443,81.97938144329896 344,79 C 403.4884020618557,76.02061855670104 475.2426362297498,87.50515463917526 535,94 C 594.7573637702502,100.49484536082474 642.5178571428571,102 711,92 C 779.4821428571429,82 868.6859351988218,60.49484536082474 928,54 C 987.3140648011782,47.50515463917526 1016.7384020618558,56.02061855670103 1061,59 C 1105.2615979381442,61.97938144329897 1164.3604565537555,59.422680412371136 1230,62 C 1295.6395434462445,64.57731958762886 1367.8197717231224,72.28865979381443 1440,80 C 1440,80 1440,400 1440,400 Z");
            }

            100% {
                d: path("M 0,400 C 0,400 0,80 0,80 C 56.809462444771725,71.1209499263623 113.61892488954345,62.2418998527246 169,64 C 224.38107511045655,65.7581001472754 278.3337628865979,78.15335051546391 337,81 C 395.6662371134021,83.84664948453609 459.04602356406485,77.14469808541973 517,82 C 574.9539764359351,86.85530191458027 627.4821428571429,103.26785714285714 701,102 C 774.5178571428571,100.73214285714286 869.0254050073638,81.78387334315168 932,73 C 994.9745949926362,64.21612665684832 1026.416237113402,65.59664948453609 1082,73 C 1137.583762886598,80.40335051546391 1217.309646539028,93.82952871870398 1281,96 C 1344.690353460972,98.17047128129602 1392.345176730486,89.08523564064801 1440,80 C 1440,80 1440,400 1440,400 Z");
            }
        }

        .path-1 {
            animation: pathAnim-1 4s;
            animation-timing-function: linear;
            animation-iteration-count: infinite;
        }

        @keyframes pathAnim-1 {
            0% {
                d: path("M 0,400 C 0,400 0,160 0,160 C 54.34149484536083,145.6104565537555 108.68298969072166,131.22091310751105 168,135 C 227.31701030927834,138.77908689248895 291.60953608247416,160.7268041237113 358,159 C 424.39046391752584,157.2731958762887 492.87886597938154,131.87187039764362 547,131 C 601.1211340206185,130.12812960235638 640.875,153.78571428571428 701,164 C 761.125,174.21428571428572 841.6211340206188,170.98527245949924 904,176 C 966.3788659793812,181.01472754050076 1010.6404639175255,194.27319587628867 1073,186 C 1135.3595360824745,177.72680412371133 1215.8170103092784,147.92194403534612 1280,140 C 1344.1829896907216,132.07805596465388 1392.0914948453608,146.03902798232696 1440,160 C 1440,160 1440,400 1440,400 Z");
            }

            25% {
                d: path("M 0,400 C 0,400 0,160 0,160 C 65.27393225331369,167.49079528718704 130.54786450662738,174.9815905743741 186,179 C 241.45213549337262,183.0184094256259 287.0824742268041,183.56443298969072 346,175 C 404.9175257731959,166.43556701030928 477.1222385861561,148.76067746686303 537,144 C 596.8777614138439,139.23932253313697 644.4285714285714,147.39285714285714 704,154 C 763.5714285714286,160.60714285714286 835.1634756995581,165.66789396170842 910,166 C 984.8365243004419,166.33210603829158 1062.9175257731958,161.93556701030928 1112,156 C 1161.0824742268042,150.06443298969072 1181.1664212076582,142.5898379970545 1231,143 C 1280.8335787923418,143.4101620029455 1360.4167893961708,151.70508100147276 1440,160 C 1440,160 1440,400 1440,400 Z");
            }

            50% {
                d: path("M 0,400 C 0,400 0,160 0,160 C 54.760493372606774,164.8637702503682 109.52098674521355,169.7275405007364 169,171 C 228.47901325478645,172.2724594992636 292.6765463917526,169.95360824742266 355,174 C 417.3234536082474,178.04639175257734 477.77282768777627,188.45802650957293 539,180 C 600.2271723122237,171.54197349042707 662.2321428571428,144.2142857142857 717,136 C 771.7678571428572,127.7857142857143 819.2986008836524,138.68483063328426 882,153 C 944.7013991163476,167.31516936671574 1022.5734536082473,185.0463917525773 1094,179 C 1165.4265463917527,172.9536082474227 1230.407584683358,143.12960235640648 1287,136 C 1343.592415316642,128.87039764359352 1391.796207658321,144.43519882179675 1440,160 C 1440,160 1440,400 1440,400 Z");
            }

            75% {
                d: path("M 0,400 C 0,400 0,160 0,160 C 41.69606038291603,158.04657584683358 83.39212076583206,156.09315169366715 154,156 C 224.60787923416794,155.90684830633285 324.1275773195877,157.67396907216497 391,163 C 457.8724226804123,168.32603092783503 492.09756995581733,177.21097201767304 536,174 C 579.9024300441827,170.78902798232696 633.4821428571429,155.48214285714286 695,153 C 756.5178571428571,150.51785714285714 825.9738586156111,160.8604565537555 888,159 C 950.0261413843889,157.1395434462445 1004.6224226804125,143.07603092783506 1066,148 C 1127.3775773195875,152.92396907216494 1195.5364506627393,176.83541973490426 1259,182 C 1322.4635493372607,187.16458026509574 1381.2317746686304,173.58229013254788 1440,160 C 1440,160 1440,400 1440,400 Z");
            }

            100% {
                d: path("M 0,400 C 0,400 0,160 0,160 C 54.34149484536083,145.6104565537555 108.68298969072166,131.22091310751105 168,135 C 227.31701030927834,138.77908689248895 291.60953608247416,160.7268041237113 358,159 C 424.39046391752584,157.2731958762887 492.87886597938154,131.87187039764362 547,131 C 601.1211340206185,130.12812960235638 640.875,153.78571428571428 701,164 C 761.125,174.21428571428572 841.6211340206188,170.98527245949924 904,176 C 966.3788659793812,181.01472754050076 1010.6404639175255,194.27319587628867 1073,186 C 1135.3595360824745,177.72680412371133 1215.8170103092784,147.92194403534612 1280,140 C 1344.1829896907216,132.07805596465388 1392.0914948453608,146.03902798232696 1440,160 C 1440,160 1440,400 1440,400 Z");
            }
        }

        .path-2 {
            animation: pathAnim-2 4s;
            animation-timing-function: linear;
            animation-iteration-count: infinite;
        }

        @keyframes pathAnim-2 {
            0% {
                d: path("M 0,400 C 0,400 0,240 0,240 C 72.96778350515464,245.45342415316642 145.93556701030928,250.90684830633285 210,249 C 274.0644329896907,247.09315169366715 329.22551546391753,237.82603092783506 375,241 C 420.77448453608247,244.17396907216494 457.16237113402053,259.78902798232696 521,261 C 584.8376288659795,262.21097201767304 676.1250000000001,249.01785714285714 739,246 C 801.8749999999999,242.98214285714286 836.3376288659792,250.1395434462445 883,247 C 929.6623711340208,243.8604565537555 988.5244845360826,230.4239690721649 1053,229 C 1117.4755154639174,227.5760309278351 1187.5644329896907,238.16458026509574 1253,242 C 1318.4355670103093,245.83541973490426 1379.2177835051548,242.91770986745212 1440,240 C 1440,240 1440,400 1440,400 Z");
            }

            25% {
                d: path("M 0,400 C 0,400 0,240 0,240 C 54.676730486008836,249.2829528718704 109.35346097201767,258.5659057437408 173,254 C 236.64653902798233,249.4340942562592 309.2628865979382,231.01932989690718 372,233 C 434.7371134020618,234.98067010309282 487.5949926362297,257.35677466863035 537,264 C 586.4050073637703,270.64322533136965 632.3571428571429,261.5535714285714 704,247 C 775.6428571428571,232.4464285714286 872.9764359351987,212.42893961708396 932,213 C 991.0235640648013,213.57106038291604 1011.737113402062,234.73067010309276 1070,242 C 1128.262886597938,249.26932989690724 1224.0751104565538,242.6483799705449 1292,240 C 1359.9248895434462,237.3516200294551 1399.962444771723,238.67581001472755 1440,240 C 1440,240 1440,400 1440,400 Z");
            }

            50% {
                d: path("M 0,400 C 0,400 0,240 0,240 C 69.93538291605303,234.76914580265097 139.87076583210606,229.53829160530194 195,236 C 250.12923416789394,242.46170839469806 290.4523195876288,260.61597938144325 352,260 C 413.5476804123712,259.38402061855675 496.3199558173786,239.99779086892494 559,230 C 621.6800441826214,220.00220913107506 664.2678571428571,219.39285714285714 725,218 C 785.7321428571429,216.60714285714286 864.6086156111929,214.4307805596465 927,218 C 989.3913843888071,221.5692194403535 1035.2976804123714,230.88402061855672 1091,236 C 1146.7023195876286,241.11597938144328 1212.2006627393225,242.03313696612665 1272,242 C 1331.7993372606775,241.96686303387335 1385.8996686303387,240.98343151693666 1440,240 C 1440,240 1440,400 1440,400 Z");
            }

            75% {
                d: path("M 0,400 C 0,400 0,240 0,240 C 67.4913475699558,244.23287923416788 134.9826951399116,248.46575846833576 189,244 C 243.0173048600884,239.53424153166424 283.5605670103093,226.36984536082477 343,226 C 402.4394329896907,225.63015463917523 480.7750368188513,238.05486008836522 542,238 C 603.2249631811487,237.94513991163478 647.3392857142857,225.4107142857143 698,230 C 748.6607142857143,234.5892857142857 805.867820324006,256.30228276877756 871,261 C 936.132179675994,265.69771723122244 1009.1894329896909,253.38015463917526 1080,248 C 1150.8105670103091,242.61984536082474 1219.374447717231,244.17709867452135 1279,244 C 1338.625552282769,243.82290132547865 1389.3127761413843,241.91145066273933 1440,240 C 1440,240 1440,400 1440,400 Z");
            }

            100% {
                d: path("M 0,400 C 0,400 0,240 0,240 C 72.96778350515464,245.45342415316642 145.93556701030928,250.90684830633285 210,249 C 274.0644329896907,247.09315169366715 329.22551546391753,237.82603092783506 375,241 C 420.77448453608247,244.17396907216494 457.16237113402053,259.78902798232696 521,261 C 584.8376288659795,262.21097201767304 676.1250000000001,249.01785714285714 739,246 C 801.8749999999999,242.98214285714286 836.3376288659792,250.1395434462445 883,247 C 929.6623711340208,243.8604565537555 988.5244845360826,230.4239690721649 1053,229 C 1117.4755154639174,227.5760309278351 1187.5644329896907,238.16458026509574 1253,242 C 1318.4355670103093,245.83541973490426 1379.2177835051548,242.91770986745212 1440,240 C 1440,240 1440,400 1440,400 Z");
            }
        }

        .path-3 {
            animation: pathAnim-3 4s;
            animation-timing-function: linear;
            animation-iteration-count: infinite;
        }

        @keyframes pathAnim-3 {
            0% {
                d: path("M 0,400 C 0,400 0,320 0,320 C 65.7428203240059,326.45379234167893 131.4856406480118,332.90758468335787 192,339 C 252.5143593519882,345.09241531664213 307.80025773195877,350.82345360824746 372,347 C 436.19974226804123,343.17654639175254 509.31332842415316,329.7986008836524 566,322 C 622.6866715758468,314.2013991163476 662.9464285714286,311.9821428571429 718,311 C 773.0535714285714,310.0178571428571 842.9009572901325,310.2728276877761 906,308 C 969.0990427098675,305.7271723122239 1025.449742268041,300.9265463917526 1082,309 C 1138.550257731959,317.0734536082474 1195.3000736377026,338.0209867452136 1255,342 C 1314.6999263622974,345.9790132547864 1377.3499631811487,332.9895066273932 1440,320 C 1440,320 1440,400 1440,400 Z");
            }

            25% {
                d: path("M 0,400 C 0,400 0,320 0,320 C 72.41402798232696,315.3726067746686 144.8280559646539,310.7452135493373 197,305 C 249.1719440353461,299.2547864506627 281.1018041237113,292.3917525773196 329,295 C 376.8981958762887,297.6082474226804 440.76472754050076,309.6877761413844 519,310 C 597.2352724594992,310.3122238586156 689.8392857142857,298.85714285714283 750,305 C 810.1607142857143,311.14285714285717 837.8781296023566,334.88365243004415 891,340 C 944.1218703976434,345.11634756995585 1022.6481958762884,331.6082474226804 1087,331 C 1151.3518041237116,330.3917525773196 1201.5290868924892,342.6833578792342 1258,343 C 1314.4709131075108,343.3166421207658 1377.2354565537553,331.6583210603829 1440,320 C 1440,320 1440,400 1440,400 Z");
            }

            50% {
                d: path("M 0,400 C 0,400 0,320 0,320 C 57.35162002945506,306.69311487481593 114.70324005891013,293.3862297496318 175,300 C 235.29675994108987,306.6137702503682 298.5386597938145,333.14819587628864 363,338 C 427.4613402061855,342.85180412371136 493.14212076583203,326.0209867452136 542,325 C 590.857879234168,323.9790132547864 622.8928571428571,338.7678571428571 689,344 C 755.1071428571429,349.2321428571429 855.2864506627394,344.90758468335787 920,341 C 984.7135493372606,337.09241531664213 1013.9613402061855,333.60180412371136 1065,330 C 1116.0386597938145,326.39819587628864 1188.8681885125186,322.6851988217968 1255,321 C 1321.1318114874814,319.3148011782032 1380.5659057437406,319.6574005891016 1440,320 C 1440,320 1440,400 1440,400 Z");
            }

            75% {
                d: path("M 0,400 C 0,400 0,320 0,320 C 47.39745949926362,301.8530927835052 94.79491899852724,283.7061855670103 160,291 C 225.20508100147276,298.2938144329897 308.21778350515467,331.02835051546396 382,343 C 455.78221649484533,354.97164948453604 520.3339469808542,346.180412371134 567,329 C 613.6660530191458,311.819587628866 642.4464285714286,286.25 697,291 C 751.5535714285714,295.75 831.8803387334315,330.819587628866 901,341 C 970.1196612665685,351.180412371134 1028.0322164948452,336.4716494845361 1086,323 C 1143.9677835051548,309.5283505154639 1201.990795287187,297.2938144329897 1261,297 C 1320.009204712813,296.7061855670103 1380.0046023564064,308.3530927835052 1440,320 C 1440,320 1440,400 1440,400 Z");
            }

            100% {
                d: path("M 0,400 C 0,400 0,320 0,320 C 65.7428203240059,326.45379234167893 131.4856406480118,332.90758468335787 192,339 C 252.5143593519882,345.09241531664213 307.80025773195877,350.82345360824746 372,347 C 436.19974226804123,343.17654639175254 509.31332842415316,329.7986008836524 566,322 C 622.6866715758468,314.2013991163476 662.9464285714286,311.9821428571429 718,311 C 773.0535714285714,310.0178571428571 842.9009572901325,310.2728276877761 906,308 C 969.0990427098675,305.7271723122239 1025.449742268041,300.9265463917526 1082,309 C 1138.550257731959,317.0734536082474 1195.3000736377026,338.0209867452136 1255,342 C 1314.6999263622974,345.9790132547864 1377.3499631811487,332.9895066273932 1440,320 C 1440,320 1440,400 1440,400 Z");
            }
        }

        .weizhi {
            position: fixed;
            bottom: 0;
            left: 0;
            display: flex;
            flex-direction: column;
            align-items: flex-end;
        }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
    <div class="moon">
        <img src="https://img95.699pic.com/element/40161/6685.png_300.png" alt="月亮是古人寄托思念,就像你在我心里的位置一样">
    </div>
    <div class="verse">
        <p>同从弟南斋玩月忆山阴崔少府</p>
        <p>王昌龄(唐)</p>
        <p>高卧南斋时,开帷月初吐。</p>
        <p>清辉澹水木,演漾在窗户。</p>
        <p>荏苒几盈虚,澄澄变今古。</p>
        <p>美人清江畔,是夜越吟苦。</p>
        <p>千里共如何,微风吹兰杜。</p>
    </div>
    <svg width="100%" id="svg" viewBox="0 0 1440 400" xmlns="http://www.w3.org/2000/svg"
        class="transition weizhi duration-300 ease-in-out delay-150">
        <defs>
            <linearGradient id="gradient" x1="48%" y1="0%" x2="52%" y2="100%">
                <stop offset="5%" stop-color="#00000044"></stop>
                <stop offset="95%" stop-color="#9900ef44"></stop>
            </linearGradient>
        </defs>
        <path
            d="M 0,400 C 0,400 0,80 0,80 C 56.809462444771725,71.1209499263623 113.61892488954345,62.2418998527246 169,64 C 224.38107511045655,65.7581001472754 278.3337628865979,78.15335051546391 337,81 C 395.6662371134021,83.84664948453609 459.04602356406485,77.14469808541973 517,82 C 574.9539764359351,86.85530191458027 627.4821428571429,103.26785714285714 701,102 C 774.5178571428571,100.73214285714286 869.0254050073638,81.78387334315168 932,73 C 994.9745949926362,64.21612665684832 1026.416237113402,65.59664948453609 1082,73 C 1137.583762886598,80.40335051546391 1217.309646539028,93.82952871870398 1281,96 C 1344.690353460972,98.17047128129602 1392.345176730486,89.08523564064801 1440,80 C 1440,80 1440,400 1440,400 Z"
            stroke="none" stroke-width="0" fill="url(#gradient)"
            class="transition-all duration-300 ease-in-out delay-150 path-0"></path>
        <defs>
            <linearGradient id="gradient" x1="48%" y1="0%" x2="52%" y2="100%">
                <stop offset="5%" stop-color="#00000066"></stop>
                <stop offset="95%" stop-color="#9900ef66"></stop>
            </linearGradient>
        </defs>
        <path
            d="M 0,400 C 0,400 0,160 0,160 C 54.34149484536083,145.6104565537555 108.68298969072166,131.22091310751105 168,135 C 227.31701030927834,138.77908689248895 291.60953608247416,160.7268041237113 358,159 C 424.39046391752584,157.2731958762887 492.87886597938154,131.87187039764362 547,131 C 601.1211340206185,130.12812960235638 640.875,153.78571428571428 701,164 C 761.125,174.21428571428572 841.6211340206188,170.98527245949924 904,176 C 966.3788659793812,181.01472754050076 1010.6404639175255,194.27319587628867 1073,186 C 1135.3595360824745,177.72680412371133 1215.8170103092784,147.92194403534612 1280,140 C 1344.1829896907216,132.07805596465388 1392.0914948453608,146.03902798232696 1440,160 C 1440,160 1440,400 1440,400 Z"
            stroke="none" stroke-width="0" fill="url(#gradient)"
            class="transition-all duration-300 ease-in-out delay-150 path-1"></path>
        <defs>
            <linearGradient id="gradient" x1="48%" y1="0%" x2="52%" y2="100%">
                <stop offset="5%" stop-color="#00000088"></stop>
                <stop offset="95%" stop-color="#9900ef88"></stop>
            </linearGradient>
        </defs>
        <path
            d="M 0,400 C 0,400 0,240 0,240 C 72.96778350515464,245.45342415316642 145.93556701030928,250.90684830633285 210,249 C 274.0644329896907,247.09315169366715 329.22551546391753,237.82603092783506 375,241 C 420.77448453608247,244.17396907216494 457.16237113402053,259.78902798232696 521,261 C 584.8376288659795,262.21097201767304 676.1250000000001,249.01785714285714 739,246 C 801.8749999999999,242.98214285714286 836.3376288659792,250.1395434462445 883,247 C 929.6623711340208,243.8604565537555 988.5244845360826,230.4239690721649 1053,229 C 1117.4755154639174,227.5760309278351 1187.5644329896907,238.16458026509574 1253,242 C 1318.4355670103093,245.83541973490426 1379.2177835051548,242.91770986745212 1440,240 C 1440,240 1440,400 1440,400 Z"
            stroke="none" stroke-width="0" fill="url(#gradient)"
            class="transition-all duration-300 ease-in-out delay-150 path-2"></path>
        <defs>
            <linearGradient id="gradient" x1="48%" y1="0%" x2="52%" y2="100%">
                <stop offset="5%" stop-color="#000000ff"></stop>
                <stop offset="95%" stop-color="#9900efff"></stop>
            </linearGradient>
        </defs>
        <path
            d="M 0,400 C 0,400 0,320 0,320 C 65.7428203240059,326.45379234167893 131.4856406480118,332.90758468335787 192,339 C 252.5143593519882,345.09241531664213 307.80025773195877,350.82345360824746 372,347 C 436.19974226804123,343.17654639175254 509.31332842415316,329.7986008836524 566,322 C 622.6866715758468,314.2013991163476 662.9464285714286,311.9821428571429 718,311 C 773.0535714285714,310.0178571428571 842.9009572901325,310.2728276877761 906,308 C 969.0990427098675,305.7271723122239 1025.449742268041,300.9265463917526 1082,309 C 1138.550257731959,317.0734536082474 1195.3000736377026,338.0209867452136 1255,342 C 1314.6999263622974,345.9790132547864 1377.3499631811487,332.9895066273932 1440,320 C 1440,320 1440,400 1440,400 Z"
            stroke="none" stroke-width="0" fill="url(#gradient)"
            class="transition-all duration-300 ease-in-out delay-150 path-3"></path>
    </svg>
</body>
<script>
    // 坐标
    class Crood {
        constructor(x = 0, y = 0) {
            this.x = x;
            this.y = y;
        }
        setCrood(x, y) {
            this.x = x;
            this.y = y;
        }
        copy() {
            return new Crood(this.x, this.y);
        }
    }

    // 流星
    class ShootingStar {
        constructor(init = new Crood, final = new Crood, size = 3, speed = 200, onDistory = null) {
            this.init = init; // 初始位置
            this.final = final; // 最终位置
            this.size = size; // 大小
            this.speed = speed; // 速度:像素/s

            // 飞行总时间
            this.dur = Math.sqrt(Math.pow(this.final.x - this.init.x, 2) + Math.pow(this.final.y - this.init.y, 2)) * 1000 / this.speed;

            this.pass = 0; // 已过去的时间
            this.prev = this.init.copy(); // 上一帧位置
            this.now = this.init.copy(); // 当前位置
            this.onDistory = onDistory;
        }
        draw(ctx, delta) {
            this.pass += delta;
            this.pass = Math.min(this.pass, this.dur);

            let percent = this.pass / this.dur;

            this.now.setCrood(
                this.init.x + (this.final.x - this.init.x) * percent,
                this.init.y + (this.final.y - this.init.y) * percent
            );

            // canvas
            ctx.strokeStyle = '#fff';
            ctx.lineCap = 'round';
            ctx.lineWidth = this.size;
            ctx.beginPath();
            ctx.moveTo(this.now.x, this.now.y);
            ctx.lineTo(this.prev.x, this.prev.y);
            ctx.stroke();

            this.prev.setCrood(this.now.x, this.now.y);
            if (this.pass === this.dur) {
                this.distory();
            }
        }
        distory() {
            this.onDistory && this.onDistory();
        }
    }


    // 流星雨
    class MeteorShower {
        constructor(cvs, ctx) {
            this.cvs = cvs;
            this.ctx = ctx;
            this.stars = [];
            this.T;
            this.stop = false;
            this.playing = false;
        }

        // 生成随机位置的流星
        createStar() {
            let angle = Math.PI / 3;
            let distance = Math.random() * 800;
            let init = new Crood((Math.random() * 1.2 * this.cvs.width - 50), Math.random() * 300 | 0);
            let final = new Crood(init.x + distance * Math.cos(angle), init.y + distance * Math.sin(angle));
            let size = Math.random() * 4;
            let speed = Math.random() * 400 + 100;
            let star = new ShootingStar(
                init, final, size, speed,
                () => { this.remove(star) }
            );
            return star;
        }

        remove(star) {
            this.stars = this.stars.filter((s) => { return s !== star });
        }

        update(delta) {
            if (!this.stop && this.stars.length < 40) {
                this.stars.push(this.createStar());
            }
            this.stars.forEach((star) => {
                star.draw(this.ctx, delta);
            });
        }

        tick() {
            if (this.playing) return;
            this.playing = true;

            let now = (new Date()).getTime();
            let last = now;
            let delta;

            let _tick = () => {
                if (this.stop && this.stars.length === 0) {
                    cancelAnimationFrame(this.T);
                    this.playing = false;
                    return;
                }

                delta = now - last;
                delta = delta > 500 ? 30 : (delta < 16 ? 16 : delta);
                last = now;
                // console.log(delta);

                this.T = requestAnimationFrame(_tick);

                ctx.save();
                ctx.globalCompositeOperation = "destination-in";
                ctx.fillStyle = 'rgba(0,0,0,0.8)'; // 每一帧用 “半透明” 的背景色清除画布
                ctx.fillRect(0, 0, cvs.width, cvs.height);
                ctx.restore();
                this.update(delta);
            }
            _tick();
        }

        // 开始
        start() {
            this.stop = false;
            this.tick();
        }

        // 暂停
        stop() {
            this.stop = true;
        }
    }

    let cvs = document.querySelector('canvas');
    let ctx = cvs.getContext('2d');
    let meteorShower = new MeteorShower(cvs, ctx);
    meteorShower.start();
</script>
<script>
    // 当在画布上动画时,最好使用requestAnimationFrame而不是setTimeout或setInterval
    // 但并非所有浏览器都支持,有时需要一个前缀,所以我们需要一个垫片
    window.requestAnimFrame = (function () {
        return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            function (callback) {
                window.setTimeout(callback, 1000 / 60);
            };
    })();

    // 现在,我们将为演示设置基本变量
    var canvas = document.getElementById('canvas'),
        ctxyi = canvas.getContext('2d'),
        // 全屏幕尺寸
        cw = window.innerWidth,
        ch = window.innerHeight,
        // 烟花集合
        fireworks = [],
        // 粒子集合
        particles = [],
        // 从色调
        hue = 120,
        // 当使用点击方式发射烟花爆竹时,如果一次性发射过多烟花爆竹,则没有限制,每5个循环发射一次
        limiterTotal = 5,
        limiterTick = 0,
        // 这将计时烟花的自动发射,每80个循环滴答一次发射
        timerTotal = 80,
        timerTick = 0,
        mousedown = false,
        // 鼠标x坐标,
        mx,
        // 鼠标y坐标
        my;

    // 设置画布尺寸
    canvas.width = cw;
    canvas.height = ch;

    // 现在我们将为整个演示设置函数占位符

    // get a random number within a range
    function random(min, max) {
        return Math.random() * (max - min) + min;
    }

    // 计算两点之间的距离
    function calculateDistance(p1x, p1y, p2x, p2y) {
        var xDistance = p1x - p2x,
            yDistance = p1y - p2y;
        return Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2));
    }

    // 创建烟花
    function Firework(sx, sy, tx, ty) {
        //实际的坐标
        this.x = sx;
        this.y = sy;
        // 起始坐标
        this.sx = sx;
        this.sy = sy;
        // 目标坐标
        this.tx = tx;
        this.ty = ty;
        // 从起点到目标的距离
        this.distanceToTarget = calculateDistance(sx, sy, tx, ty);
        this.distanceTraveled = 0;
        // 跟踪每一个烟花的过去的坐标来创建一个步道效果,增加坐标计数来创建更突出的步道
        this.coordinates = [];
        this.coordinateCount = 3;
        // 用当前坐标填充初始坐标集合
        while (this.coordinateCount--) {
            this.coordinates.push([this.x, this.y]);
        }
        this.angle = Math.atan2(ty - sy, tx - sx);
        this.speed = 2;
        this.acceleration = 1.05;
        this.brightness = random(50, 70);
        // 圆形目标指示器半径
        this.targetRadius = 1;
    }

    // 更新烟花
    Firework.prototype.update = function (index) {
        // 移除坐标数组中的最后一项
        this.coordinates.pop();
        // 将当前坐标添加到数组的开头
        this.coordinates.unshift([this.x, this.y]);

        // 循环圆形目标指示器半径
        if (this.targetRadius < 8) {
            this.targetRadius += 0.3;
        } else {
            this.targetRadius = 1;
        }

        // 加快燃放速度
        this.speed *= this.acceleration;

        // 根据角度和速度得到当前速度
        var vx = Math.cos(this.angle) * this.speed,
            vy = Math.sin(this.angle) * this.speed;
        // 在施加的速度下,烟花会飞多远?
        this.distanceTraveled = calculateDistance(this.sx, this.sy, this.x + vx, this.y + vy);

        // 如果移动的距离(包括速度)大于到目标的初始距离,那么就已经到达目标
        if (this.distanceTraveled >= this.distanceToTarget) {
            createParticles(this.tx, this.ty);
            // 删除烟花,使用传递给更新函数的索引来确定要删除哪个
            fireworks.splice(index, 1);
        } else {
            // 目标未到达,继续前进
            this.x += vx;
            this.y += vy;
        }
    }

    // 画烟花
    Firework.prototype.draw = function () {
        ctxyi.beginPath();
        //移动到集合中最后一个跟踪的坐标,然后画一条线到cunront vond v
        ctxyi.moveTo(this.coordinates[this.coordinates.length - 1][0], this.coordinates[this.coordinates.length - 1][1]);
        ctxyi.lineTo(this.x, this.y);
        ctxyi.strokeStyle = 'hsl(' + hue + ', 100%, ' + this.brightness + '%)';
        ctxyi.stroke();

        ctxyi.beginPath();
        // 用一个跳动的圆圈画出这个烟花的目标
        ctxyi.arc(this.tx, this.ty, this.targetRadius, 0, Math.PI * 2);
        ctxyi.stroke();
    }

    // 创建粒子
    function Particle(x, y) {
        this.x = x;
        this.y = y;
        // 跟踪每个粒子的过去坐标来创建一个轨迹效果,增加坐标计数来创建更突出的轨迹
        this.coordinates = [];
        this.coordinateCount = 5;
        while (this.coordinateCount--) {
            this.coordinates.push([this.x, this.y]);
        }
        // 以弧度为单位,在所有可能的方向上设置一个随机角度
        this.angle = random(0, Math.PI * 2);
        this.speed = random(1, 10);
        // 摩擦会使粒子减速
        this.friction = 0.95;
        // 重力会将粒子向下拉
        this.gravity = 1;
        //将色调设置为整体色调变量的随机数+-20
        this.hue = random(hue - 20, hue + 20);
        this.brightness = random(50, 80);
        this.alpha = 1;
        // 设置粒子淡出的速度
        this.decay = random(0.015, 0.03);
    }

    // 更新粒子
    Particle.prototype.update = function (index) {
        // 移除坐标数组中的最后一项
        this.coordinates.pop();
        // 将当前坐标添加到数组的开头
        this.coordinates.unshift([this.x, this.y]);
        // 使粒子减速
        this.speed *= this.friction;
        // 适用于速度
        this.x += Math.cos(this.angle) * this.speed;
        this.y += Math.sin(this.angle) * this.speed + this.gravity;
        // 让粒子淡出
        this.alpha -= this.decay;

        // 根据传入的索引,在alpha足够低的时候移除粒子
        if (this.alpha <= this.decay) {
            particles.splice(index, 1);
        }
    }

    // 得出粒子
    Particle.prototype.draw = function () {
        ctxyi.beginPath();
        // 移动到集合中最后一个被跟踪的坐标,然后画一条到当前x和y的直线
        ctxyi.moveTo(this.coordinates[this.coordinates.length - 1][0], this.coordinates[this.coordinates.length - 1][1]);
        ctxyi.lineTo(this.x, this.y);
        ctxyi.strokeStyle = 'hsla(' + this.hue + ', 100%, ' + this.brightness + '%, ' + this.alpha + ')';
        ctxyi.stroke();
    }

    // 创建粒子组/爆炸
    function createParticles(x, y) {
        // 增加粒子数更大的爆炸,小心帆布性能打击与增加粒子尽管
        var particleCount = 30;
        while (particleCount--) {
            particles.push(new Particle(x, y));
        }
    }

    // 主要演示循环
    function loop() {
        // 这个函数将无休止地运行requestAnimationFrame
        requestAnimFrame(loop);

        // 随着时间的推移,增加色调以获得不同颜色的烟花
        hue += 0.5;

        // 规则v. clearRect()将用于清除画布
        // 我们想要创建一个拖尾效果
        // 将复合操作设置为destination-out将允许我们以特定的不透明度清除画布,而不是完全擦拭它
        ctxyi.globalCompositeOperation = 'destination-out';
        // 减小alpha属性以创建更突出的轨迹
        ctxyi.fillStyle = 'rgba(0, 0, 0, 0.5)';
        ctxyi.fillRect(0, 0, cw, ch);
        // 将复合操作更改回主模式
        // 打火机创造明亮的亮点,因为烟花和粒子相互重叠
        ctxyi.globalCompositeOperation = 'lighter';

        // 循环遍历每个烟花,绘制它,更新它
        var i = fireworks.length;
        while (i--) {
            fireworks[i].draw();
            fireworks[i].update(i);
        }

        // 循环遍历每个粒子,绘制它,更新它
        var i = particles.length;
        while (i--) {
            particles[i].draw();
            particles[i].update(i);
        }

        // 当鼠标不按下时,自动向随机坐标发射烟花
        if (timerTick >= timerTotal) {
            if (!mousedown) {
                // 在屏幕底部中间开始放烟花,然后设置随机目标坐标,随机y坐标将在屏幕上半部分范围内设置
                fireworks.push(new Firework(cw / 2, ch, random(0, cw), random(0, ch / 2)));
                timerTick = 0;
            }
        } else {
            timerTick++;
        }

        // 当鼠标按下时,限制烟花的发射速度
        if (limiterTick >= limiterTotal) {
            if (mousedown) {
                // 在屏幕底部中间启动烟花,然后将当前鼠标坐标设置为目标
                fireworks.push(new Firework(cw / 2, ch, mx, my));
                limiterTick = 0;
            }
        } else {
            limiterTick++;
        }
    }

    // 鼠标事件绑定
    // 取消鼠标移动上的鼠标坐标的日期
    canvas.addEventListener('mousemove', function (e) {
        mx = e.pageX - canvas.offsetLeft;
        my = e.pageY - canvas.offsetTop;
    });

    // 切换鼠标按下状态并防止画布被选中
    canvas.addEventListener('mousedown', function (e) {
        e.preventDefault();
        mousedown = true;
    });

    canvas.addEventListener('mouseup', function (e) {
        e.preventDefault();
        mousedown = false;
    });

    // 一旦窗户装好,我们就可以放烟花了!
    window.onload = loop;
</script>

</html>

代码效果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值