L
O
A
D
I
N
G

添加行星特效


添加行星特效

前几天在网上看到一个很好看的行星动画特效。于是就想着把它加入到自己的网站里,虽然会影响网站性能,但是对这种真的没有抵抗力!

效果

日日夜夜自转的行星

源码

源码:html5 canvas绘制陨石围绕天体运动的动画特效源码 -HTML代码下载 -时代Java,与您同行! (nowjava.com)

解压后的文件夹中应该包括:

  • css文件夹,里面有1个css文件
  • js文件夹,里面有8个js文件
  • 1个index.html文件
  • 1个说明文件

步骤

  1. 找到matery下的配置文件config.yml,找到menu属性,添加页面名称和图标。这里是我的配置

    name: 碎星海
    url: /asteroids
    icon: fas fa-meteor
  2. themes\matery\layout下新建asteroids.ejs,粘入上面提到的index.html代码

  3. themes\matery\source\css下新建asteroids.css,粘入上面的css代码

  4. themes\matery\source\js下新建asteroids文件夹,将上面的8个js文件夹放到该文件夹中

注意

  1. 需要根据自己的代码存放位置手动修改index.html代码中的路径

  2. 可能会出现页面渲染阻塞的情况,博主使用原代码,推送到网站后,就出现了动画效果卡顿的情况,这时候可以通过使用 deferasync 属性来实现异步加载,确保脚本不会阻塞页面的渲染。

    这里记录一下代码的优化过程(已弃用,点击跳转到最新解决方法最新解决方法

    1. 使用原代码(页面渲染阻塞)

      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <meta charset="UTF-8">
          <title>乱石穿空</title>
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <link rel="stylesheet" href="/css/asteroids.css">
      </head>
      
      <body>
          <div id="container"></div>
          <script src='/js/asteroids/three.min.js'></script>
          <script src='/js/asteroids/CopyShader.js'></script>
          <script src='/js/asteroids/EffectComposer.js'></script>
          <script src='/js/asteroids/FilmPass.js'></script>
          <script src='/js/asteroids/FilmShader.js'></script>
          <script src='/js/asteroids/ShaderPass.js'></script>
          <script src='/js/asteroids/RenderPass.js'></script>
          <script src="/js/asteroids/index.js"></script>
      </body>
      
      </html>
    2. 使用 defer 属性实现异步加载,确保脚本将在文档解析完毕后异步加载,并在文档完成解析后立即执行。这样可以确保页面加载不会被脚本的加载和执行所阻塞。之前一直以为是代码和原博客里的代码产生冲突,一直没能解决,成了萦绕在心头的一大问题,今日终于成功解决!ヾ(≧▽≦*)o

      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <meta charset="UTF-8">
          <title>乱石穿空</title>
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <link rel="stylesheet" href="/css/asteroids.css">
      </head>
      
      <body>
          <div id="container"></div>
          <script src='/js/asteroids/three.min.js' defer></script>
          <script src='/js/asteroids/CopyShader.js' defer></script>
          <script src='/js/asteroids/EffectComposer.js' defer></script>
          <script src='/js/asteroids/FilmPass.js' defer></script>
          <script src='/js/asteroids/FilmShader.js' defer></script>
          <script src='/js/asteroids/ShaderPass.js' defer></script>
          <script src='/js/asteroids/RenderPass.js' defer></script>
          <script src="/js/asteroids/index.js" defer></script>
      </body>
      
      </html>
    3. 感觉代码看起来有些冗杂,修改了一下,看起来更专业了😎

      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <meta charset="UTF-8">
          <title>乱石穿空</title>
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <link rel="stylesheet" href="/css/asteroids.css">
      </head>
      <body>
          <div id="container"></div>
          <script>
              window.addEventListener('DOMContentLoaded', (event) => {
                  const path = "/js/asteroids/";
                  const scripts = [
                      'three.min.js',
                      'CopyShader.js',
                      'EffectComposer.js',
                      'FilmPass.js',
                      'FilmShader.js',
                      'ShaderPass.js',
                      'RenderPass.js',
                      'index.js'
                  ];
      
                  scripts.forEach(script => {
                      const scriptTag = document.createElement('script');
                      scriptTag.src = path + script;
                      scriptTag.defer = true;
                      document.body.appendChild(scriptTag);
                  });
              });
          </script>
      </body>
      
      </html>

更新

链式加载

最近发现行星页面变黑了,刷新了几次又好了,时灵时不灵。打开控制台发现如下报错

报错

因为数组中其他js代码都是依赖于Three.js的,所以需要把Three.js在其他js代码文件之前加载。因为前面使用异步加载,所以我猜想可能是异步加载的顺序问题引发了这个问题。

尽管使用了defer属性,这意味着脚本会在文档解析完成后,DOMContentLoaded事件触发之前执行,但由于它们是并行加载的,所以并不能保证它们按照数组中的顺序执行完毕。

为了强制执行脚本的加载顺序,决定采取一种链式加载的方法,即只有当一个脚本加载并执行完成后,才开始加载下一个脚本。

<body>
    <div id="container"></div>
    <script>
        function loadScript(index) {
            if (index >= scripts.length) return; // 所有脚本加载完毕

            const scriptTag = document.createElement('script');
            scriptTag.src = path + scripts[index];
            scriptTag.onload = function() {
                // 当前脚本加载并执行完毕后,加载下一个脚本
                loadScript(index + 1);
            };
            scriptTag.onerror = function() {
                console.error(`Failed to load script ${scripts[index]}`);
            };
            document.body.appendChild(scriptTag);
        }

        const path = "/js/asteroids/";
        const scripts = [
            'three.min.js',
            'CopyShader.js',
            'EffectComposer.js',
            'FilmPass.js',
            'FilmShader.js',
            'ShaderPass.js',
            'RenderPass.js',
            'index.js'
        ];

        // 开始加载脚本
        loadScript(0);
    </script>
</body>

修改完后再次打开控制台,可以看到相关问题已经消失了,并且动画正常显示。YEAH!(~ ̄▽ ̄)~

链式加载

适配小屏

突然发现行星动画没有适配小屏幕,导致在小屏幕上出现这种情况

未适配小屏

修改样式的css代码

原样式代码

* {
  margin: 0;
  padding: 0;
  outline: 0
}

body,
html {
  width: 100%;
  height: 100%;
  background: #000;
  overflow: hidden
}

#container {
  width: 100%;
  height: 100%
}

添加响应式布局,以适应不同的屏幕尺寸

/* 基础样式 */
* {
  margin: 0;
  padding: 0;
  outline: 0;
}

html,
body {
  width: 100%;
  height: 100%;
  background: #000;
  overflow: hidden;
}

#container {
  width: 100%;
  height: 100%;
}

/* 小屏幕(移动设备)的样式 */
@media only screen and (max-width: 600px) {
  #container {
    width: 100%;
    height: 100%;
    overflow: auto;
  }
}

/* 中等屏幕(平板设备)的样式 */
@media only screen and (min-width: 601px) and (max-width: 992px) {
  #container {
    width: 100%;
    height: 100%;
    overflow: auto;
  }
}

/* 大屏幕(桌面设备)的样式 */
@media only screen and (min-width: 993px) {
  #container {
    width: 100%;
    height: 100%;
    overflow: hidden;
  }
}

修改后正常显示(≧∇≦)ノ

适配小屏

其他

当浏览器解析 HTML 文档时,遇到 <script> 标签时,它会停止解析文档并立即下载并执行脚本。在这个过程中,浏览器的渲染也会被阻塞,直到脚本加载和执行完成。这可能会导致页面加载速度变慢,特别是当页面中有多个脚本需要加载时。

为了解决这个问题,HTML5 引入了 deferasync 属性,这两个属性都是用来控制脚本的加载和执行方式的。

defer 属性

defer 属性告诉浏览器立即下载脚本文件,但延迟执行脚本,直到文档解析完成后再执行。具体来说:

  • 延迟执行脚本,意味着脚本会在文档解析完成后按照它们在文档中出现的顺序执行。
  • 多个带有 defer 属性的脚本会按照它们在文档中的顺序顺序执行。
  • 脚本会在 DOMContentLoaded 事件之前执行,确保它们在文档的其他内容加载之前执行。

async 属性

async 属性告诉浏览器立即下载脚本文件,并且异步执行脚本,不会阻止文档的解析。具体来说:

  • 异步执行脚本,意味着脚本会在下载完成后尽快执行,不会等待其他脚本或文档解析完成。
  • 多个带有 async 属性的脚本的执行顺序是不确定的,谁先下载完成就会先执行谁。
  • 脚本的执行可能在文档的其他内容加载之前或之后。

选择 defer 还是 async?

  • 如果脚本之间的执行顺序很重要,并且你希望它们在文档解析完成后按顺序执行,那么应该使用 defer 属性。
  • 如果脚本之间的执行顺序不重要,并且你希望尽快执行脚本,不阻塞页面的渲染,那么可以使用 async 属性。
  • 如果你有多个脚本需要异步加载,并且它们之间没有依赖关系,那么可以考虑使用 async 属性以提高页面加载性能。

总之,defer 属性适用于需要保持脚本执行顺序的情况,而 async 属性适用于无序的异步加载脚本。


文章作者: loyeh
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 loyeh !
评论
  目录