3D可视化编辑器模版

体验地址:http://mute.turntip.cn

在这里插入图片描述
在这里插入图片描述
整个搭建平台核心模块包含如下几个部分:
3D场景渲染
组件拖拽系统
元素编辑功能
状态管理
历史记录与撤销/重做
技术栈
前端框架与库
React 18
用于构建用户界面的JavaScript库
Next.js 14
React框架,提供服务端渲染、路由等功能
TypeScript
静态类型检查的JavaScript超集
Three.js
3D图形库,用于在浏览器中渲染3D场景
React Three Fiber
Three.js的React渲染器
React Three Drei
Three.js的React组件集合
Tailwind CSS
实用优先的CSS框架
Lucide React
现代图标库
状态管理与工具
Zustand
轻量级状态管理库
UUID
用于生成唯一标识符
HTML5 Drag and Drop API
原生拖放功能实现
i3D Editor采用了组件化、模块化的架构设计,主要分为以下几个部分:

架构图
在这里插入图片描述
数据流
状态管理
使用Zustand管理应用状态,包括场景元素、选中元素等
用户交互
用户通过界面进行交互,如拖拽组件、选择元素、调整属性等
状态更新
交互触发状态更新,通过Zustand的actions修改状态
UI渲染
状态变化触发UI重新渲染,包括3D场景和编辑界面
历史记录
状态变化被记录到历史栈中,支持撤销/重做操作
核心功能实现
3D场景渲染
i3D Editor使用React Three Fiber和React Three Drei来简化Three.js的使用,实现3D场景的渲染。

// Canvas设置
<Canvascamera={{ position: viewMode === "3D" ? [5, 5, 5] : [0, 5, 0], fov: 50 }}shadowsclassName="w-full h-full"
><ambientLight intensity={0.5} /><directionalLight position={[10, 10, 10]} intensity={1} castShadow />{/* 网格 */}<Gridargs={[100, 100]}cellSize={1}cellThickness={0.5}cellColor="#a0a0ff"sectionSize={5}sectionThickness={1}sectionColor="#2080ff"fadeDistance={50}fadeStrength={1.5}followCamera={false}infiniteGrid/>{/* 场景对象 */}{elements.map((element) => (<SceneObjectkey={element.id}element={element}isSelected={selectedElement?.id === element.id}onClick={() => setSelectedElement(element)}viewMode={viewMode}activeMode={activeMode}/>))}{/* 控制器 */}<OrbitControls makeDefault enabled={!selectedElement || activeMode !== "select"} /><Environment preset="studio" />
</Canvas>

组件拖拽系统
i3D Editor实现了一个基于HTML5 Drag and Drop API的拖拽系统,允许用户从组件库拖拽元素到3D场景中。


// 拖拽开始
const handleDragStart = (event, elementType) => {event.dataTransfer.setData("application/element-type", elementType);event.dataTransfer.effectAllowed = "copy";// 通知父组件拖拽开始onStartDrag(elementType);
};
// 拖拽结束
const handleDrop = (event) => {event.preventDefault();if (!isDragging || !draggedElementType) return;// 获取Canvas容器的位置和尺寸const rect = canvasContainerRef.current.getBoundingClientRect();// 计算鼠标在Canvas中的相对位置const x = ((event.clientX - rect.left) / rect.width) * 2 - 1;const y = -((event.clientY - rect.top) / rect.height) * 2 + 1;// 创建射线并计算与平面的交点const raycaster = new THREE.Raycaster();raycaster.setFromCamera(new THREE.Vector2(x, y),new THREE.PerspectiveCamera(50, rect.width / rect.height, 0.1, 1000));const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);const target = new THREE.Vector3();raycaster.ray.intersectPlane(plane, target);// 添加元素到场景addElement({type: draggedElementType,position: { x: target.x, y: 0, z: target.z },rotation: { x: 0, y: 0, z: 0 },scale: 1,material: "standard",color: getDefaultColor(draggedElementType),name: getElementName(draggedElementType),displayTip: false,});// 重置拖拽状态setIsDragging(false);setDraggedElementType(null);
};

元素编辑功能
i3D Editor提供了浮动工具栏,允许用户对选中的元素进行编辑操作,如移动、旋转、复制和删除等。

// 浮动工具栏定位
<divref={toolbarRef}className={`absolute bg-white rounded-lg shadow-lg z-20 flex ${isHorizontalLayout ? "flex-row" : "flex-col"} items-center p-2`}style={{left: `${toolbarPosition.x}px`,top: `${toolbarPosition.y}px`,transform: "translate(-50%, -120%)",transition: "left 0.2s ease, top 0.2s ease",}}
>{/* 工具按钮 */}<buttonclassName={`p-1.5 rounded-full hover:bg-blue-100 ${activeMode === "select" ? "text-blue-500" : ""}`}onClick={() => handleToolClick("select")}title="选择工具"><MousePointer className="h-4 w-4" /></button>{/* 更多工具按钮... */}
</div>

状态管理实现
i3D Editor使用Zustand进行状态管理,包括场景元素、选中元素等。


// 元素存储
export const useElementStore = create<ElementStore>((set) => ({elements: [],selectedElement: null,addElement: (element) =>set((state) => ({elements: [...state.elements, { ...element, id: uuidv4() }],})),updateElement: (id, updates) =>set((state) => ({elements: state.elements.map((element) => element.id === id ? { ...element, ...updates } : element),selectedElement:state.selectedElement?.id === id ? { ...state.selectedElement, ...updates } : state.selectedElement,})),removeElement: (id) =>set((state) => ({elements: state.elements.filter((element) => element.id !== id),selectedElement: state.selectedElement?.id === id ? null : state.selectedElement,})),setSelectedElement: (element) => set({ selectedElement: element }),// 更多actions...
}));

i3D Editor实现了历史记录功能,支持撤销和重做操作。


// 历史记录状态
const [history, setHistory] = useState<HistoryState[]>([]);
const [historyIndex, setHistoryIndex] = useState(-1);
const [isUndoRedo, setIsUndoRedo] = useState(false);
// 监听元素变化,更新历史记录
useEffect(() => {if (isUndoRedo) {setIsUndoRedo(false);return;}if (historyIndex >= 0) {const currentState: HistoryState = {elements: JSON.parse(JSON.stringify(elements)),selectedElementId: selectedElement?.id || null,};// 检查是否与当前历史记录状态相同const lastState = history[historyIndex];const isEqual =JSON.stringify(lastState.elements) === JSON.stringify(currentState.elements) &&lastState.selectedElementId === currentState.selectedElementId;if (!isEqual) {// 如果在历史记录中间进行了操作,则删除后面的历史记录const newHistory = history.slice(0, historyIndex + 1);setHistory([...newHistory, currentState]);setHistoryIndex(historyIndex + 1);}}
}, [elements, selectedElement, history, historyIndex]);
// 撤销操作
const handleUndo = () => {if (historyIndex > 0) {setIsUndoRedo(true);const prevState = history[historyIndex - 1];// 应用历史状态loadElements(prevState.elements);// 恢复选中状态if (prevState.selectedElementId) {const selectedElement = prevState.elements.find((el) => el.id === prevState.selectedElementId);if (selectedElement) {setSelectedElement(selectedElement);}} else {setSelectedElement(null);}setHistoryIndex(historyIndex - 1);}
};
// 重做操作
const handleRedo = () => {if (historyIndex &lt; history.length - 1) {setIsUndoRedo(true);const nextState = history[historyIndex + 1];// 应用历史状态loadElements(nextState.elements);// 恢复选中状态if (nextState.selectedElementId) {const selectedElement = nextState.elements.find((el) => el.id === nextState.selectedElementId);if (selectedElement) {setSelectedElement(selectedElement);}} else {setSelectedElement(null);}setHistoryIndex(historyIndex + 1);}
};

上面就是核心功能实现,当然项目还有很多需要优化,这里只是给大家提供一个方案思路参考,如果感兴趣可以在github上下载代码学习。

github地址:https://github.com/MrXujiang/3D-Editor

flowmix/docx多模态文档引擎,目前也在持续更新中,欢迎体验参考:https://flowmix.turntip.cn

多维表格 flowmix/mute

体验地址:http://mute.turntip.cn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/77904.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“连接世界的桥梁:深入理解计算机网络应用层”

一、引言 当你浏览网页、发送邮件、聊天或观看视频时&#xff0c;这一切都离不开计算机网络中的应用层&#xff08;Application Layer&#xff09;。 应用层是网络协议栈的最顶层&#xff0c;直接为用户的各种应用程序提供服务。它为用户进程之间建立通信桥梁&#xff0c;屏蔽了…

JavaScript 代码搜索框

1. 概述与需求分析 功能&#xff1a;在网页中实时搜索用户代码、关键字&#xff1b;展示匹配行、文件名&#xff1b;支持高亮、正则、模糊匹配。非功能&#xff1a;大文件集&#xff08;几十万行&#xff09;、高并发、响应 <100ms&#xff1b;支持增量索引和热更新。 2. …

【运维】Ubuntu apt 更新失败?Temporary failure resolving ‘cn.archive.ubuntu.com‘ 问题

Ubuntu apt 更新失败&#xff1f;Temporary failure resolving ‘cn.archive.ubuntu.com’ 问题 在使用 Ubuntu 时&#xff0c;你是否遇到过这样一个烦人的错误&#xff1a; Temporary failure resolving ‘cn.archive.ubuntu.com’ 如果你也踩坑了&#xff0c;别慌&#xff0…

Uniapp:showLoading(等待加载)

目录 一、出现场景二、效果展示三、具体使用一、出现场景 在项目的开发中,我们经常会请求后台接口返回数据,但是每一个接口返回数据的时间不一致,有的快,有的慢,这个时候如果不加一个遮罩层,接口返回慢的时候,非常影响用户体验 二、效果展示 三、具体使用 显示加载框…

【11408学习记录】英语书信通知写作模板大全:5个高分句式+使用场景解析,速存每日一句拆解练习!

书信/通知写作锦囊妙句 英语写作——19个锦囊妙句妙句9妙句10妙句11妙句12妙句13 每日一句词汇第一步&#xff1a;找谓语第二步&#xff1a;断句第三步&#xff1a;简化让步状语从句限定性同位语从句主句 英语 写作——19个锦囊妙句 妙句9 故宫在中国人民中很受欢迎/评价很高…

Unity 粒子同步,FishNet

Github的工程 同步画面 使用FishNet插件同步&#xff0c;可使用这个选项来克隆第二个项目进行测试

【hadoop】案例:MapReduce批量写入HBase

1.需求分析 我们仍然以美国各个气象站每年的气温数据集为例&#xff0c;现在要求使用MapReduce读取该数据集&#xff0c;然后批量写入HBase数据库&#xff0c;最后利用HBase shell根据行键即席查询气温数据。 2.数据集准备 数据集的文件名为temperature.log&#xff0c;里面包含…

【linux网络】网络基础概念

1. 初始协议 1.1 OSI 七层模型 OSI&#xff08;Open System Interconnection&#xff0c;开放系统互连&#xff09;七层网络模型称为开放式系统互联参考模型&#xff0c;是一个逻辑上的定义和规范&#xff1b; 把网络从逻辑上分为了 7 层. 每一层都有相关、相对应的物理设备&a…

【Android】谈谈DexClassLoader

一,Dex和Jar DEX 文件(Dalvik Executable)相较于普通的 JAR(Java 字节码 .class 文件)进行了多方面的优化,主要是为了适应 Android 设备的性能和资源限制(例如内存、存储空间和处理能力)。以下是 DEX 文件的一些具体优化点: 1. 内存占用优化 合并类文件: DEX 文件将…

【Flutter】Unity 三端封装方案:Android / iOS / Web

关联文档&#xff1a;【方案分享】Flutter Unity 跨平台三维渲染架构设计全解&#xff1a;插件封装、通信机制与热更新机制—— 支持 Android/iOS/Web 的 3D 内容嵌入与远程资源管理&#xff0c;助力 XR 项目落地 —— 支持 Android/iOS/Web 的 3D 内容嵌入与远程资源管理&…

Html1

一&#xff0c;HTML概述 网页开发需要学习的知识&#xff1a; html css javaScript 两个框架 VUE.js ElementUI UI user interface 用户界面 HTML xml 可扩展标记语言-->存储数据 Markup Language标签语言都会提供各种标…

一、I/O的相关概念

I/O的相关概念 1、I/O I/O即Input和Output&#xff0c;用户进程执行I/O操作&#xff0c;归结起来&#xff0c;也就是向操作系统发出请求&#xff0c;读请求就把数据填到缓冲区里&#xff0c;写数据就把缓冲区里数据排干&#xff0c;目的地可以是磁盘也可以是其他通道。进程通…

出现Invalid bound statement (not found)问题的原因可能有哪些

1.全局配置文件没配好&#xff1f; 检查全局配置文件application.properties或application.yml是否配置扫描mapper包的文件路径 #mybatis配置mapper文件路径 #mybatis.mapper-locationsclasspath:/mapper/*.xml #mybatis-plus配置mapper文件路径 mybatis-plus.mapper-locatio…

第十节:文本编辑

理论知识 文本编辑器的基本概念&#xff1a;文本编辑器是用于创建和编辑文本文件的工具。在 Linux 系统中&#xff0c;常见的文本编辑器有 vi、vim、nano 等。vi 和 vim 编辑器&#xff1a;vi 是一款经典的文本编辑器&#xff0c;vim 是 vi 的增强版&#xff0c;提供了更多的功…

部署一个自己的Spring Ai 服务(deepseek/通义千问)

Spring Boot 无缝接入 DeepSeek 和通义千问请求日志记录及其ip黑白名单 SpringBoot版本 3.2.0 JDK 版本为17 redis 3.2.0 mybatis 3.0.3 依赖引入 关键依赖 <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai-sp…

组装 (DIY) 一台显示器 (4K 屏支持 4 画面分屏 PBP 1080p x4)

首发日期 2025-04-26, 以下为原文内容: 家里的 PC 主机比较多, 如果同时开机, 显示器就不够用了. 因为穷, 窝租住的房间又很小, 放不下很多显示器. 所以, 窝希望买一台支持 分屏 功能的显示器. 最好是 4K 分辨率 (3840x2160) 的屏幕, 然后 4 分屏 (有 4 个 DP 或 HDMI 输入接口…

[Java入门]抽象类和接口

[Java入门]抽象类和接口 1. 抽象类1.1 抽象类的概念1.2 抽象类语法1.3 抽象类特性1.4 抽象类的作用 2. 接口2.1 接口的概念2.2 语法规则2.3 接口使用2.4 接口特性2.5 实现多个接口2.6 接口间的继承2.7 抽象类和接口的区别 3. Object类3.1 获取对象信息3.2 对象比较equals方法 1…

聚焦数字中国|AI赋能与安全守护:Coremail引领邮件办公智能化转型

4月28日&#xff0c;第八届数字中国建设峰会在福州拉开序幕。当天&#xff0c;数字中国新产品新技术发布会开讲&#xff0c;Coremail受邀亮相现场&#xff0c;与与会嘉宾分享AI在邮件产品领域的最新应用成果和实践经验。 Coremail首席客户代表刘子建以《AI赋能与安全守护&#…

Qt官方案例知识点总结(拖放操作——Drag And Drop Robot )

-------------------------------------------------------------------------------------------------------------------------------- QPixmap轮廓剪裁 去掉Pixmap的外围部分&#xff0c;如下&#xff1a; QPixmap pixmap("./img"); //调用createHeuristicMas…

【LLM】MOE混合专家大模型综述(重要模块原理)

note 当前的 MoE 架构就是一个用显存换训练时长/推理延迟的架构MoE 目前的架构基本集中在于将原先 GPT 每层的 FFN 复制多份作为 n 个 expert&#xff0c;并增加一个 router&#xff0c;用来计算每个 token 对应到哪个 FFN&#xff08;一般采用每个 token 固定指派 n 个 exper…