内容嵌入

1 3D模型

最简单的插入 3D 模型是三个步骤 :

  1. 获得一个 .glb 格式的 3D 模型

  2. 引入谷歌的 <model-viewer> 组件

  3. 然后插入原始的 {=html} 页面元素

值得一提的是 :3D模型文件 .glb 是单文件二进制,最省事, .gltf 会附带.bin 和贴图文件容易漏

1.1 范例

下面用 40% 的视口高度加载并显示一个宇航员 :

```{=html}
<model-viewer src="Attachments/NeilArmstrong.glb" 
camera-controls="" auto-rotate="" style="width: 100%; height: 40vh;"> </model-viewer>
```

2 嵌入游戏

下面嵌入了一个游戏 labels_and_texts, 为了节省带宽,点击才会加载 :

注意, 这个游戏是从 Godot 的 demo projects 下载的,需要 HTTP(S) 访问(不能用 file://),浏览器需支持 WebGL


它的原理是用一张图片作为游戏的封面, 没有加载游戏的时候显示图片, 点击以后再调用脚本加载游戏 :

```{=html}
<div class="lf-embed"
     data-src="Attachments/labels_and_texts/index.html"
     data-title="3D Labels and Texts 游戏"
     style="position:relative;width:100%;height:60vh;border-radius:6px;overflow:hidden;background:#0d1117;">
  <button type="button" class="lf-play"
          style="position:absolute;inset:0;width:100%;height:100%;padding:0;margin:0;cursor:pointer;border:none;background:#0d1117;">
    <img src="Attachments/labels_and_texts/index.png" alt="游戏封面,点击加载"
         style="width:100%;height:100%;object-fit:cover;display:block;">
  </button>
</div>
```

利用了脚本 lf-embed.js 进行点击加载, 它被放置到了页面的 header 中 :

---
resources:
  - "Attachments/labels_and_texts/*"  # Godot 的网页游戏, labels and texts
  - "Attachments/lf-embed.js"  # 点击加载游戏脚本
format:
  html:
    include-in-header:  
      - text: |                
          <script src="Attachments/lf-embed.js"></script>
---
lf-embed.js
(function () {
  if (window.__lfEmbedInit) return;
  window.__lfEmbedInit = true;
  document.addEventListener('click', function (e) {
    var btn = e.target.closest('.lf-embed .lf-play');
    if (!btn) return;
    var box = btn.closest('.lf-embed');
    var f = document.createElement('iframe');
    f.src = box.getAttribute('data-src');
    f.title = box.getAttribute('data-title') || 'embedded content';
    f.setAttribute('allow', 'autoplay; fullscreen; gamepad; xr-spatial-tracking');
    f.setAttribute('allowfullscreen', '');
    f.style.cssText = 'width:100%;height:100%;border:none;background:#000;display:block;';
    box.innerHTML = '';
    box.appendChild(f);
  });
})();