Skip to content

示例系统与浏览器

示例系统由 Three.js 的 400+ 交互式演示集合以及用于浏览它们的基于 Web 的浏览器界面组成。该系统包括标准化的示例编写模式、基于 JSON 的组织结构(files.jsontags.json),以及带缩略图预览的可搜索浏览器 UI。浏览器在 iframe 中加载示例,维护基于 URL 的导航,并与文档系统共享 UI 架构(6.3)。

有关验证这些示例的测试基础设施的信息,请参阅测试基础设施(6.4)。有关同样使用示例的可视化编辑器,请参阅可视化编辑器(6.1)。

文件结构与数据源

示例浏览器由一个静态 HTML 文件组成,该文件从 JSON 配置文件动态加载示例元数据。

SVG
100%

files.json 结构

files.json 清单将示例组织成类别。每个类别是一个对象键,包含示例文件名数组(不带 .html 扩展名):

{
  "webgl": [
    "webgl_animation_keyframes",
    "webgl_buffergeometry"
  ],
  "webgpu": [
    "webgpu_compute_particles"
  ],
  "misc": [
    "misc_controls_orbit"
  ]
}

tags.json 结构

tags.json 文件将示例名称映射到搜索标签数组和元数据标志:

{
  "misc_exporter_gcode": ["community"],
  "webgl_clipping": ["solid"],
  "webgl_interactive_cubes": ["raycast", "highlight"]
}

"community" 标签标识社区贡献的示例,这些示例会获得特殊视觉处理。

UI 架构

示例浏览器使用带卡片式导航的面板-查看器布局,与文档系统的架构匹配。

SVG
100%

面板组件

面板在左侧占据固定的 300px 宽度(移动端全宽)。它包含:

面板使用 CSS 类管理状态:

  • .open - 在移动端展开面板
  • .searchFocused - 搜索激活时调整 UI
  • .minimal - 隐藏截图预览,显示紧凑列表

查看器 iframe

iframe 显示选中的示例,并具有 WebXR 的全屏权限:

<iframe id="viewer" name="viewer" allow="fullscreen; xr-spatial-tracking"></iframe>

位置计算考虑面板宽度:padding-left: var(--panel-width)files/main.css451)。

卡片生成

每个示例由 createLink() 创建的卡片元素表示:

SVG
100%

卡片模板包括:

  • 截图图像:懒加载,400px 宽,16:9 宽高比
  • 社区标签:如果示例的标签数组中有 "community" 则显示
  • 格式化标题:由 getName() 生成,去除前缀并将下划线转换为斜杠

导航与路由

浏览器使用基于哈希的路由来维护指向特定示例的深度链接。

SVG
100%

链接注册

在导航构建期间,每个示例在两个数据结构中注册:

  1. links 对象examples/index.html57):将文件名映射到 DOM 元素以进行选择高亮
  2. validRedirects Mapexamples/index.html58):将文件名映射到带 .html 扩展名的完整路径以确保安全

安全模式防止不受信任的 URL 重定向:

if ( validRedirects.has( file ) === true ) {
    selectFile( file );
    viewer.src = validRedirects.get( file );
}

点击处理

卡片点击被拦截以防止在修改的点击(Ctrl+Click、中键点击)时导航:

link.querySelector( 'a[target="viewer"]' ).addEventListener( 'click', function ( event ) {
    if ( event.button !== 0 || event.ctrlKey || event.altKey || event.metaKey ) return;
    selectFile( file );
} );

查看源码按钮

浮动“查看源码”按钮(examples/index.html43)在选中示例时动态配置:

viewSrcButton.style.display = '';
viewSrcButton.href = 'https://github.com/mrdoob/three.js/blob/master/examples/' + selected + '.html';
viewSrcButton.title = 'View source code for ' + getName( selected ) + ' on GitHub';

搜索与过滤系统

浏览器实现带多词支持和类别感知过滤的客户端搜索。

SVG
100%

多词搜索模式

搜索使用前瞻模式匹配任意顺序的所有单词:

function escapeRegExp( string ) {
    string = string.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' );
    return '(?=.*' + string.split( ' ' ).join( ')(?=.*' ) + ')';
}

示例:"webgl animation" 变为 (?=.*webgl)(?=.*animation),匹配包含这两个单词的任何示例。

标签集成

filterExample() 函数将文件名与标签数组合并以进行全面匹配:

function filterExample( file, exp, tags ) {
    const link = links[ file ];
    if ( file in tags ) file += ' ' + tags[ file ].join( ' ' );
    const res = file.replace( /_+/g, ' ' ).match( exp );
    // ...
}

这允许用户搜索像 "raycast""community""ambient occlusion" 这样的标签。

URL 状态持久化

搜索查询反映在 URL 中以便共享链接:

if ( v !== '' ) {
    window.history.replaceState( {}, '', '?q=' + v + window.location.hash );
} else {
    window.history.replaceState( {}, '', window.location.pathname + window.location.hash );
}

页面加载时,提取查询并自动填充:

filterInput.value = extractQuery();
if ( filterInput.value !== '' ) {
    panel.classList.add( 'searchFocused' );
    updateFilter( files, tags );
}

截图系统

每个示例都有对应的截图用作预览缩略图。

截图规格

属性
位置examples/screenshots/
命名{filename}.jpg(匹配示例名称)
尺寸400px 宽(16:9 宽高比)
格式带压缩的 JPEG
加载通过 loading="lazy" 属性懒加载

来源: examples/index.html218

显示模式

浏览器通过预览图标支持两种显示模式:

卡片模式(默认):

  • 完整截图预览,56.25% 底部内边距(16:9 比例)
  • 截图使用 position: absolute 居中填充容器
  • 卡片背景色和内边距

精简模式.minimal 类):

  • 截图通过 display: none 隐藏
  • 纯文本列表视图
  • 减少的内边距和外边距

截图生成

截图由测试基础设施(6.4)使用 Puppeteer 捕获渲染的示例生成。命名约定确保自动对应:

webgl_animation_keyframes.html → screenshots/webgl_animation_keyframes.jpg

与文档系统的共享架构

示例浏览器和文档系统(6.3)共享大量 UI 基础设施,以提供一致的用户体验。

SVG
100%

通用 UI 组件

两个系统使用相同的 HTML 结构和 CSS 选择器:

组件选择器用途
面板容器#panel带导航的固定侧边栏
头部#header标题和章节标签
搜索输入框#filterInput文本过滤字段
清除按钮#clearSearchButton重置搜索状态
内容区域#content可滚动导航
展开按钮#expandButton移动端菜单切换
面板遮罩#panelScrim移动端覆盖背景
查看器框架iframe[name="viewer"]内容显示区域

响应式行为

两个系统在 640px 处共享相同的移动端断点:

@media all and ( max-width: 640px ) {
    #panel {
        position: absolute;
        width: 100%;
        height: var(--header-height);
    }
    #panel.open {
        height: 100%;
    }
}

在移动端:

  • 面板折叠为仅头部
  • 展开按钮变为可见
  • 面板从右侧滑入
  • 遮罩覆盖层使背景内容变暗

样式差异

虽然共享布局,但系统在内容样式上有所不同:

示例浏览器

  • 带缩略图的卡片网格(files/main.css559-604
  • 16:9 宽高比的封面图像容器
  • 社区标签徽章
  • 预览切换图标

文档系统

  • 带类别的分层文本列表
  • 带语法高亮的搜索结果
  • 成员函数表示法(例如 BoxHelper.update()
  • 可折叠部分

示例文件组织

示例遵循严格的命名约定,编码其类别和功能重点。

命名模式

{category}_{topic}[_{variant}].html

示例:

  • webgl_animation_keyframes.html
  • webgpu_compute_particles_snow.html
  • misc_controls_orbit.html

类别前缀

前缀数量(约)描述
webgl_100+WebGL 渲染器示例
webgpu_40+WebGPU 渲染器示例
webgl2_5+WebGL 2 特定功能
webxr_10+WebXR 沉浸式体验
css2d_, css3d_5+CSS 渲染技术
misc_20+控制器、导出器、实用工具
physics_10+物理引擎集成

名称格式化

getName() 函数将文件名转换为显示名称:

function getName( file ) {
    const name = file.split( '_' );
    name.shift(); // 移除类别前缀
    return name.join( ' / ' );
}

示例:

  • webgl_animation_keyframesanimation / keyframes
  • webgpu_compute_particlescompute / particles
  • misc_controls_orbitcontrols / orbit

与测试基础设施的集成

虽然示例浏览器主要是导航工具,但它与测试基础设施(6.4)中描述的自动化测试系统共享基础设施:

  • 截图验证:缩略图由捕获回归测试图像的相同 Puppeteer 进程生成
  • 示例枚举:两者都使用 files.json 作为示例存在的真实来源
  • 命名约定:一致的命名支持为每个示例自动生成测试
  • iframe 加载:测试系统使用相同的基于 iframe 的加载方法在隔离环境中渲染示例

浏览器作为可视化索引,开发者可以在运行自动化测试前手动验证示例行为。