如何使用Theatre.js 0.7.0创建引人入胜的动画

在现代Web开发中,交互性和动画已经成为了设计吸引人的用户体验的不可或缺的一部分。Theatre.js是一个强大的JavaScript库,它使得创建高度交互性的Web动画变得容易。在本文中,我们将探讨Theatre.js的一些主要功能,并通过一个实际的示例来演示如何使用它来创建引人入胜的Web动画。

什么是Theatre.js?

Theatre.js是一个用于创建Web动画的JavaScript库,它旨在简化动画的制作过程并提供更多的交互性。它构建在Three.js之上,Three.js是一个用于创建3D图形的流行库。通过Theatre.js,您可以轻松地制作2D和3D动画,包括交互式场景、角色动画和特效。 以下是一些Theatre.js的主要功能:

  • 剧场(Theatre): Theatre.js提供了一个剧场的概念,您可以在其中定义和组织您的动画场景。这使得动画的管理变得更加有条不紊。
  • 演员(Actors): 在Theatre.js中,您可以创建演员,这些演员是动画的主要参与者。您可以为演员定义外观、动作和交互行为。
  • 相机(Cameras): Theatre.js支持不同的相机类型,包括透视相机和正交相机,以满足不同场景的需求。
  • 时间轴(Timeline): 您可以使用时间轴来控制动画的时间流逝,以便在不同时间点触发不同的动作。
  • 事件处理: Theatre.js允许您轻松处理交互事件,如鼠标点击、键盘输入和触摸事件。

⠀现在,让我们通过一个官网的示例来深入了解如何使用Theatre.js来创建一个交互式的Web动画。

实例:创建一个可以运行的立方体

步骤1: 安装依赖

假设我们使用pnpm作为包管理工具,

bash 复制代码
// r3f
pnpm add react three @react-three/fiber
// Theatre.js 最新版为0.7.0
pnpm add @theatre/core @theatre/studio @theatre/r3f
// threejs types
pnpm add -D @types/three

步骤2:创建一个main.tsx来写模型

ts 复制代码
import { createRoot } from 'react-dom/client' // react18
import { Canvas } from '@react-three/fiber'
import { getProject } from '@theatre/core'

const demoSheet = getProject('Demo Project').sheet('Demo Sheet') // Demo Sheet 是独一无二的id,在播放动画时需要给出

const App = () => {
  return (
    <Canvas
      camera={{
        position: [5, 5, -5],
        fov: 75,
      }} // 一个默认监视着0,0,0 position 的相机
	  gl={{ preserveDrawingBuffer: true }} // 用于显示浮窗
    >
      <ambientLight intensity={Math.PI}/> // 平行光
      <pointLight position={[1, 1, 1] intensity={Math.PI}} /> 
      <mesh>
        <boxGeometry args={[1, 1, 1]} />
        <meshStandardMaterial color="orange" />
      </mesh>
    </Canvas>
  )
}

createRoot(document.getElementById('root')!).render(<App />)

如果你使用过官网的例子你就会发现,在浏览器中渲染出的立方体表现和官方是不一样的,这里主要表现为颜色景深的区别。这其中的原由是由于threejs 引擎由v0.154.0--->v0.155.0 版本的升级导致的,原因如下: 总结一下就是,threejs154版本向155版本升级的时候,把 WebGLRenderer.useLegacyLights的默认属性由true改为了false,并且打算在165版本移除这个属性。而这个属性会影响光照强度。 想要解决这个问题可以有两种思路:

  1. 手动把原本的光照乘以PI
  2. 手动修改WebGLRenderer.useLegacyLights的值为true

步骤3: 加入studio 调试界面

ts 复制代码
import { createRoot } from 'react-dom/client' // react18
import React, { useEffect } from 'react'
import { Canvas } from '@react-three/fiber'
import studio from '@theatre/studio'
import extension from '@theatre/r3f/dist/extension'

...

const App = () => {
	useEffect(() => {
		 if (process.env.NODE_ENV === "development") {
			studio.initialize({ usePersistentStorage: false });
			studio.extend(extension);
    }

	}, [])
  return (
    <Canvas
      camera={{
        position: [5, 5, -5],
        fov: 75,
      }} // 一个默认监视着0,0,0 position 的相机
	  gl={{ preserveDrawingBuffer: true }} // 用于显示浮窗
    >
     	...
    </Canvas>
  )
}

使用studio.initialize 初始化 后,屏幕上显示如下将usePersistentStorage 的属性值设置为false 可以让该项目在调试模型下不被缓存,方便调试。

使用studio.extend(extension) 后,即可通过相机按钮开启调试控制台。

步骤4: 绑定事件,使控制台可以改变真实的three对象

ts 复制代码
...
import {editable as e, SheetProvider, PerspectiveCamera } from '@theatre/r3f

function App () => {
	return (
		<Canvas>
  			<SheetProvider sheet={getProject('Demo Project').sheet('Demo 					Sheet')}>
    		<PerspectiveCamera theatreKey="Camera" makeDefault position={[5, 				5, -5]} fov={75} lookAt={[0, 0, 0]} />
    		<ambientLight intensity={Math.PI}/>
    		<e.pointLight theatreKey="Light" position={[1, 1, 1]} intensity={Math.PI}/>
    		<e.mesh theatreKey="Cube">
      			<boxGeometry args={[1, 1, 1]} />
      			<meshStandardMaterial color="orange" />
    		</e.mesh>
  			</SheetProvider>
		</Canvas>

	)
}
...

我们使用sheetProviderthree-react-fiber 组件提供上下文 使用editable模块把three-react-fiber组件转换为可监听组件 再使用PerspectiveCamera 替换canvas的默认相机,注意要使用lookAt 使相机注视着目标。

步骤5: 使用调试控制给元素打上关键帧

步骤6: 导出动画,并使用该文件播放

在设置完关键帧后,点击左上角Demo Project ,就可以在右侧点击导出作品按钮

ts 复制代码
function App () => {
	useEffect(() => {
		demoSheet.project.ready.then(() => demoSheet.sequence.play({ iterationCount: Infinity}))
	},[])
	return (
		<Canvas>
  			<SheetProvider sheet={getProject('Demo Project').sheet('Demo 					Sheet')}>
    		<PerspectiveCamera theatreKey="Camera" makeDefault position={[5, 				5, -5]} fov={75} lookAt={[0, 0, 0]} />
    		<ambientLight intensity={Math.PI}/>
    		<e.pointLight theatreKey="Light" position={[1, 1, 1]} intensity={Math.PI}/>
    		<e.mesh theatreKey="Cube">
      			<boxGeometry args={[1, 1, 1]} />
      			<meshStandardMaterial color="orange" />
    		</e.mesh>
  			</SheetProvider>
		</Canvas>

	)
}

完整代码如下:

ts 复制代码
import './index.css'
import { createRoot } from 'react-dom/client'
import React, { useEffect } from 'react'
import { Canvas } from '@react-three/fiber'
import studio from '@theatre/studio'
import extension from '@theatre/r3f/dist/extension'
import { SheetProvider, editable as e, PerspectiveCamera } from '@theatre/r3f'
import { getProject } from '@theatre/core'
import demoProjectState from './state.json'

const App = () => {
  useEffect(() => {
    if (process.env.NODE_ENV === "development") {
      studio.initialize({ usePersistentStorage: false });
      console.log(studio);
      studio.extend(extension);
    }

    demoSheet.project.ready.then(() =>
      demoSheet.sequence.play({ iterationCount: Infinity }),
    );
  }, []);

  return (
    <Canvas>
      <Canvas gl={{ preserveDrawingBuffer: true }}>
        <SheetProvider sheet={demoSheet}>
          <PerspectiveCamera
            theatreKey='Camera'
            makeDefault
            position={[5, 5, -5]}
            lookAt={[0, 0, 0]}
            fov={75}
          />
          <ambientLight intensity={Math.PI} />
          <e.pointLight
            theatreKey='Light'
            intensity={Math.PI}
            position={[1, 1, 1]}
          />
          <e.mesh theatreKey='Cube'>
            <boxGeometry args={[1, 1, 1]} />
            <meshStandardMaterial color='orange' />
          </e.mesh>
        </SheetProvider>
      </Canvas>

    </Canvas>
  )
}

createRoot(document.getElementById('root')!).render(<App />)

让我们看下动画吧~

相关推荐
Sword991 天前
【ThreeJs原理解析】第2期 | 旋转、平移、缩放实现原理
前端·three.js·源码阅读
小白菜学前端1 天前
Threejs 材质贴图、光照和投影详解
前端·3d·three.js
破浪前行·吴2 天前
使用@react-three/fiber,@mkkellogg/gaussian-splats-3d加载.splat,.ply,.ksplat文件
前端·react.js·three.js
格瑞@_@9 天前
11.Three.js使用indexeddb前端缓存模型优化前端加载效率
前端·javascript·缓存·three.js·indexeddb缓存
谢小飞10 天前
我做了三把椅子原来纹理这样加载切换
前端·three.js
小白菜学前端10 天前
ThreeJS创建一个3D物体的基本流程
3d·three.js
茶老翁11 天前
1-初识Three.js
前端·three.js
莫石12 天前
搓绳子(直)
前端·数学·three.js
小白菜学前端13 天前
3d 添加辅助坐标器和轨道控制器
3d·three.js
孙_华鹏15 天前
threejs——实战中材质的应用
前端·three.js·数据可视化