大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。
今天给大家带来的主题是 Threlte,即 Svelte 生态的渲染器和组件库,用于在 Svelte 应用程序中以声明式和状态驱动的方式构建和渲染 Three.js 场景。话不多说,直接开始!
1.什么是 Threlte
Threlte 是 Svelte 的渲染器和组件库,用于在 Svelte 应用程序中以声明式和状态驱动的方式构建和渲染 Three.js 场景。
Threlte 的灵感来自于 react-three-fiber 的合理默认、Sveltes 反应性模型和 Svelte Cubed 的简单性和有效性。
Threlte 提供严格类型化的组件,可以快速、轻松地构建具有深度反应性和开箱即用交互性的 Three.js 场景。它还提供构建块(building blocks),以便在需要时快速扩展 Threlte。
但是,值得注意的是,Threlte 仍在积极开发中,后续可能会有突破性的变化, 更新前请检查发布说明。 安全起见,请使用 npm i @threlte/core --save-exact 安装 Threlte 以锁定版本,@threlte/extras 和 @threlte/rapier 也是如此。
目前 Threlte 在 Github 上通过 MIT 协议开源,有超过 1k 的 star、是一个值得关注的前端开源项目。
2.为什么需要 Threlte
svelte 已经有 three.js 组件库,但是 threlte 在某些方面有所不同:
合理的默认值
在介绍 threlte 之前需要重点介绍下 React-Three-Fiber,其是 ThreeJS 的 React 渲染器。使用可重用、独立的组件以声明方式构建场景,这些组件对状态做出反应,易于交互并且可以参与 React 的生态。
npm install three @types/three @react-three/fiber
与 react-three-fiber 非常相似,threlte 会将合理的默认值设置为 Three.js WebGLRenderer、所有颜色和纹理等,这使开发者可以轻松遵循色彩接收和准确性方面的最佳实践。 threlte 还通过其 <Layers> 组件使可见性管理变得非常容易。
统一帧循环(Unified frame loop)
默认情况下,threlte 仅在需要时渲染场景:如果 prop 发生更改而需要渲染场景,场景中存在任何交互式对象,或者 threlte 在任何组件中使用 useFrame。
丰富的互动性
threlte 使得可以在 Three.js 对象上使用事件,就好像它们是常规 DOM 元素一样:
<Mesh
… Interactive
on:click={onClick}>
开发者还可以监听对象离开或进入视口:
<Mesh
… viewportAware
on :viewportenter={onViewportEnter}>
TypeScript 支持
所有 threlte 组件都是用 TypeScript 编写的,因此类型支持是一等公民。
EffectComposer 支持
使用 <Pass pass={new GlitchPass()} /> 添加 Pass,threlte 将负责设置默认 RenderPass 并渲染到 EffectComposer 而不是 WebGLRenderer。
文本渲染
在文本渲染时候,threlte 使用 troika-three-text。
troika-two-text 包使用有符号距离场 (SDF) 和使用标准导数的抗锯齿功能,在 Three.js 场景中提供高质量的文本渲染。
troika-two-text 不依赖于预先生成的 SDF 纹理,而是直接使用 Typr 解析字体文件(.ttf、.otf、.woff),并在使用字形时即时生成 SDF 图集。 它还可以处理正确的字距调整、连字字形替换、从右到左/双向布局以及阿拉伯语等连接脚本。 所有字体解析、SDF 生成和字形布局均在 Web Worker 中执行,以防止丢帧。
生成 SDF 后,它会组装一个定位所有字形的几何体,并使用正确的着色器代码修补任何 Three.js 材质以渲染 SDF。 这意味着开发者仍然可以受益于 Three.js 内置材质的所有功能,例如光照、基于物理的渲染、阴影和雾。
<Text text="Hello World" />
自动处置
Svelte 了解组件生命周期,因此 Threlte 将尝试通过对所有已卸载对象调用 dispose(如果存在)以及对场景中其他任何地方未使用的所有属性递归调用 dispose 来释放资源。
访问所有区域
- 绑定到 three.js 对象实例 <Mesh … bind:mesh>
- 访问渲染器 const { renderer, invalidate } = useThrelte()
同时 threlte 非常易于扩展。
Tree-shakeble
React-Three-Fiber 非常擅长使用 Three.js 类作为 JSX 组件。 这意味着对某个 Three.js 版本没有硬依赖,并且 Three.js 中可能的所有内容也都被 React-Three-Fiber 覆盖了。
然而,有一个缺点:react-Three-Fiber 在运行时查找 Three.js 类。 这意味着即使 react-Three-Fiber 应用程序只使用了 Three.js 的一小部分,开发者也需要完整地提供 Three.js。
而 threlte 不会在运行时查找 Three.js 类,因此与 Three.js 本身相比其功能受到限制。 然而,它试图涵盖 Three.js 的大多数用例,并提供功能组件以使扩展 threlte 尽可能容易。 因此,打包器能够对 tree-shake threlte 并在某种程度上限制 Three.js 的哪些部分被打包。
3.快速入门 Threlte
安装 Threlte
Threlte 由 4 个软件包组成,可以单独安装和使用。 所有项目都需要@threlte/core 和三个包,而其他包是可选的。
- @threlte/core 和 three.js : 必需,是 three.js 和核心库,以声明式和状态驱动的方式构建 Three.js 场景。
- @threlte/preprocess:Threlte 的预处理器提供自动导入和改进的开发人员体验。
- svelte-sequential-preprocessor : 外部包,如果还需要运行其他预处理器,则需要它。
- @threlte/extras: 扩展核心功能的组件、工具、hooks 等。
- @threlte/rapier:在 Threlte 中使用 Rapier 物理引擎的组件和钩子。
- @threlte/theatre:在 Threlte 中使用动画库 Theatre.js 的组件和钩子。
- @types/three : 外部包,Three.js 的 TypeScript 类型。
使用 npm、pnpm、yarn 或您喜欢的任何其他包管理器安装包。
npm i -D three @threlte/core @threlte/preprocess svelte-sequential-preprocessor @threlte/extras @threlte/rapier @dimforge/rapier3d-compat @threlte/theatre @theatre/core @theatre/studio @types/three
配置
第一步调整 svelte.config.js,将 Threlte 的预处理器以及
svelte-sequential-preprocessor 添加到 Svelte 配置中:
import seqPreprocessor from 'svelte-sequential-preprocessor'
import { preprocessThrelte } from '@threlte/preprocess'
preprocess: seqPreprocessor([preprocess(), preprocessThrelte()])
}
export default config
接着调整 vite.config.js,如果将 Threlte 与 SvelteKit 一起使用,需要调整 Vite 配置,以防止通过 vites 外部化步骤将 three 和 troika-three-text 外部化用于 SSR。
// vite.config.js
const config = {
// …
ssr: {
noExternal: ["three", "troika-three-text"],
},
};
构建第一个 Scene
如下面代码所示:
<script>
import { Canvas, InteractiveObject, OrbitControls, T } from '@threlte/core'
import { spring } from 'svelte/motion'
import { degToRad } from 'three/src/math/MathUtils'
const scale = spring(1)
</script>
<div>
<Canvas>
<T.PerspectiveCamera makeDefault position={[10, 10, 10]} fov={24}>
<OrbitControls maxPolarAngle={degToRad(80)} enableZoom={false} target={{ y: 0.5 }} />
</T.PerspectiveCamera>
<T.DirectionalLight castShadow position={[3, 10, 10]} />
<T.DirectionalLight position={[-3, 10, -10]} intensity={0.2} />
<T.AmbientLight intensity={0.2} />
<!-- Cube -->
<T.Group scale={$scale}>
<T.Mesh position.y={0.5} castShadow let:ref>
<!-- Add interaction -->
<InteractiveObject
object={ref}
interactive
on:pointerenter={() => ($scale = 2)}
on:pointerleave={() => ($scale = 1)}
/>
<T.BoxGeometry />
<T.MeshStandardMaterial color="#333333" />
</T.Mesh>
</T.Group>
<!-- Floor -->
<T.Mesh receiveShadow rotation.x={degToRad(-90)}>
<T.CircleGeometry args={[3, 72]} />
<T.MeshStandardMaterial color="white" />
</T.Mesh>
</Canvas>
</div>
关于 Threlte 更多组件、hooks 等的用法本文不再展开,可以参考文末的资料自行阅读。
3.本文总结
本文主要和大家介绍 Threlte,即 Svelte 生态的渲染器和组件库,用于在 Svelte 应用程序中以声明式和状态驱动的方式构建和渲染 Three.js 场景。相信通过本文的阅读,大家对 Threlte 会有一个初步的了解。
因为篇幅有限,关于 Threlte 的更多用法和特性文章并没有过多展开,如果有兴趣,可以在我的主页继续阅读,同时文末的参考资料提供了大量优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏,您的支持是我不断创作的动力。
参考资料
https://github.com/threlte/threlte
https://threlte.xyz/features#easily-extendable
https://threlte.xyz/rapier/auto-colliders#properties
https://github.com/pmndrs/react-three-fiber
https://github.com/protectwise/troika/tree/main/packages/troika-three-text
https://threlte.xyz/