@ 3drisesai/3drises- 查看器
嵌入时的反应组件 3dRise (英语) 在您的应用程序的场景.
你建造在 3dRise工作室 - 创造物体、应用材料、设置动画、效果和 相互作用——然后使结果具有一个组件的回放. 现场没有配置 在代码中:几何,材料,照明,动画和相互作用都来源于你发表的作品.
有许多组成部分,主要是:
| 构成部分 | 嵌入层 |
|---|---|
<ProjectLoader /> | 整个工程——场景,相机,灯光,环境,动画,光标. 画出自己的画布. |
<ObjectNodeApi /> | 一个来自工作室的物体(及其子孙) 掉入你控制的画布中. |
准备用一些例子来应对项目: https://github.com/nadavtal/3drise-resact. [永久失效連結] (中文(简体) )
安装
npm install @3driseai/3drise-viewer
包裹船作为 仅限无害环境管理 包含捆绑的 TypeScript 声明.
同伴依赖关系
| 同伴依赖关系 | 版本 |
|---|---|
react | ^18 或者说 ^19 |
three | ^0.170 |
@react-three/fiber | ^9 |
@react-three/drei | ^10 |
@react-three/rapier | ^2 |
@gsap/react | ^2.1.2 |
npm 7+和pnpm 8+为您安装这些. 在Yarn上——经典或贝里——你需要自己加入.
three必须解决一个副本. 一个应用程序中三个.js的两个版本是经典反应 三次纤维故障——物体默默地拒绝使,instanceof检查失败 。 如果你的应用针 不同three比起^0.170在这里宣布,去除它(npm ls three检查,overrides编号 :resolutions而不是让两者都安装.
嵌入整个工程
ProjectLoader 通过 id 获取一个已公布的工程, 并自制 <Canvas>,并显示装入
指示器直到场景准备好。 这就是整个整合:
import { ProjectLoader } from '@3driseai/3drise-viewer';
export default function ProjectPage({ projectId }: { projectId: string }) {
return (
<div style={{ height: '100svh', position: 'relative' }}>
<ProjectLoader projectId={projectId} />
</div>
);
}
ProjectLoader 制作一个 <Canvas> 内部,所以它需要一个大小的家长——给包装件一个
明确高度( e)100svh, (中文(简体) ), 100% 表示大小的容器,固定像素值)或无任何效果.
反应到现场
每次回电都是可选的:
import { ProjectLoader } from '@3driseai/3drise-viewer';
import type { CreatedObjectSettings } from '@3driseai/3drise-core';
import type { Object3D } from 'three';
<ProjectLoader
projectId={projectId}
loadingIndicator={<MySpinner />}
onSceneInitialized={() => setReady(true)}
onObjectClick={(object: CreatedObjectSettings, ref: Object3D) => {
openInspector(object.meshSettings.name, ref);
}}
onObjectHover={(object, ref) => setHovered(object.id)}
/>;
控制现场(SceneHandle(中文(简体) )
onSceneReady(scene) (或 ref)将项目手柄交给你——工作室和项目自己的UI使用的同一种引擎:
scene.objects.list(); // the scene tree: [{ id, name, type, parent, visible, … }]
scene.values.set('Lamp', 'config.intensity', 3); // one live property (not saved)
scene.values.get('shell', 'config.depth'); // as the scene shows it now
scene.actions.toggle('night-mode');
scene.clips.play('spin', { speed: 1.5 });
scene.sequences.setProgress('story', 0.4); // drive a sequence from your own scroll / slider
scene.on('animationEnd', (e) => console.log(e.key));
项目按密钥(首选)、编号或确切名称处理.
<ProjectLoader /> 道具
| Prop | 类型 | 说明 |
|---|---|---|
projectId | string (必须) | 已公布的3dRise项目 Id来加载. |
loadingIndicator | React.ReactNode | 替换工程获取时显示的内置全屏加载器 . |
onSceneInitialized | () => void | 现场一旦起火. |
onObjectClick | (object: CreatedObjectSettings, ref: Object3D, event: ThreeEvent<MouseEvent>) => void | 一个场景对象被点击 . |
onObjectHover | (object: CreatedObjectSettings, ref: Object3D) => void | 指针进入了场景对象. |
onElementClick | (element: HtmlElement) => void | 项目中的一款2D UI元素被点击. |
onElementHover | (element: HtmlElement | null) => void | 指针输入/左出一个2D UI元素. |
onObjectReady | (object, ref: Object3D) => void | 现场每个物体都报告 Object3D 这里——见下文. |
onObjectDispose | (object, ref: Object3D) => void | 匹配的拆卸事件 onObjectReady。 。 。 . |
嵌入单个对象
有时候你不希望一个完整的场景——你想要一件事,你建造在工作室,放在画布里 您的应用程序已经拥有.
在 3dRise 工作室创建对象, 并给出其材料、 动画、 效果和点击
交互,发布,并复制其对象id. ObjectNodeApi 获取对象树并制作
你所配置的一切都是完整的:
import { Canvas } from '@react-three/fiber';
import { OrbitControls } from '@react-three/drei';
import { ObjectNodeApi } from '@3driseai/3drise-viewer';
import type { CameraState } from '@3driseai/3drise-core';
const cameraSettings: CameraState = {
position: [0, 2, 8],
orientation: [0, 0, 0, 1],
fov: 50,
near: 0.1,
far: 1000,
animations: [],
mouseMove: { enabled: false, properties: [] },
controls: { enabled: true, target: [0, 0, 0] },
};
export function Hero({ objectId }: { objectId: string }) {
return (
<Canvas camera={{ position: [0, 2, 8], fov: 50 }} style={{ height: '60vh' }}>
<ambientLight intensity={0.5} />
<directionalLight position={[5, 10, 5]} intensity={1.5} />
<ObjectNodeApi objectId={objectId} />
<OrbitControls />
</Canvas>
);
}
因为你拥有这里的画布, 你拥有所有围绕物体的东西.. 相机,照明,
控件和背景由您提供。 。 。 . ObjectNodeApi 只贡献对象本身, 所以
在不亮画布中没有任何传播材料的物体会变成黑色。 它让 null 直至
得到决心,所以它是安全的 立即挂起.
团体通过整个过程:如果物体在工作室里有孩子,它们就会被制成一棵树 他们自己的材料和动画.
<ObjectNodeApi /> 道具
| Prop | 类型 | 说明 |
|---|---|---|
objectId | string (必须) | 已公布的场景对象的ID来装入. |
handleObjectClick | (object: CreatedObjectSettings, ref: Object3D, event: ThreeEvent<MouseEvent>) => void | 该天体被点击。 注意名称与 ProjectLoader是因为 onObjectClick。 。 。 . |
onObjectReady | (object, ref: Object3D) => void | 该对象报告其 Object3D 这里——见下文. |
onObjectDispose | (object, ref: Object3D) => void | 匹配的撕裂事件 . |
正在获取 3.js 对象
两个部件都执行同样的两个道具,这样你就可以建立现场记录 而不接触 以证明自己:
type OnObjectReady = (object: ObjectReadySource, ref: Object3D) => void;
type OnObjectDispose = (object: ObjectReadySource, ref: Object3D) => void;
object是该对象在工作室中构建的设置。 这是一个联盟: 场景对象给 你是一个CreatedObjectSettings(与其工作室)id财务报告和审定财务报表meshSettings),而效果和光标给出 在读取字段之前缩小它。 从不null。 。 。 .ref为根Object3D刚刚挂起.- 每个
onObjectReady最终与一个onObjectDispose同一参考文献,卸载或 当组件交换其根时——所以Map从这些事件中建立起来的始终是准确的.
const objects = useRef(new Map<string, Object3D>());
<ProjectLoader
projectId={projectId}
onObjectReady={(object, ref) => objects.current.set(ref.uuid, ref)}
onObjectDispose={(object, ref) => objects.current.delete(ref.uuid)}
/>;
用录音室的标识键,先缩小 if ('meshSettings' in object) 告诉你,这是一个
CreatedObjectSettings。 。 。 .
从那里看它是平地的三.js——用活化它,用射线来对付它,把它附在你自己的逻辑上.
类型脚本
与货包一起的船舶类型 :
import type {
ObjectReadyProps,
ObjectReadySource,
OnObjectReady,
OnObjectDispose,
} from '@3driseai/3drise-viewer';
场景和对象类型来自核心包,它和这个包一起安装:
import type { CameraState, CreatedObjectSettings } from '@3driseai/3drise-core';
页:1
- 仅限无害环境管理. 没有共同JS大楼。 在 Next.js 或另一个 SSR 框架中,使查看器
客户端( e)
'use client',或动态导入ssr: false- 它触动window(原始内容存档于2018-09-29). and WebGL. - 一个入口. 从
@3driseai/3drise-viewer;没有深潜通道的输入.