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属性,添加页面名称和图标。这里是我的配置

    1
    2
    3
    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. 使用原代码(页面渲染阻塞)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      <!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

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      <!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. 感觉代码看起来有些冗杂,修改了一下,看起来更专业了😎

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      <!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事件触发之前执行,但由于它们是并行加载的,所以并不能保证它们按照数组中的顺序执行完毕。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<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代码

原样式代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
* {
margin: 0;
padding: 0;
outline: 0
}

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/* 基础样式 */
* {
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 !
评论
  目录