前端实现交互式3D人体肌肉解剖图:基于 Three.js + React Three Fiber 的完整方案


本文将详细介绍如何在前端实现一个交互式的3D人体肌肉解剖展示工具,用户可以旋转、缩放模型,点击任意肌肉查看中英文名称。

为什么要做这个?

传统的肌肉解剖学习通常依赖静态图片或昂贵的3D软件。作为健身爱好者,我希望能有一个免费、易用的在线工具来学习肌肉解剖知识。于是我决定自己动手,基于开源的 Z-Anatomy 项目,在浏览器中实现一个交互式的3D肌肉解剖图。

如果你想先体验效果,可以试试这个在线的3D肌肉功能解剖工具。

技术架构概览

┌─────────────────────────────────────────────────────────────┐ │ 用户浏览器 │ ├─────────────────────────────────────────────────────────────┤ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │ │ GLB 模型 │ -> │ Three.js │ -> │ React Three │ │ │ │ (Draco) │ │ 场景渲染 │ │ Fiber 组件 │ │ │ └─────────────┘ └─────────────┘ └─────────────────┘ │ │ │ │ │ ┌──────────────────┼──────────────────┐ │ │ v v v │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ 射线检测 │ │ 肌肉高亮 │ │ i18n 翻译 │ │ │ │ Raycaster │ │ 材质切换 │ │ 中英文名称 │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────────────┘ 

模型来源与处理

Z-Anatomy 开源项目

Z-Anatomy 是一个开源的人体解剖学 Blender 项目,包含完整的人体肌肉、骨骼、器官等结构。原始文件约 300MB,包含 1000+ 个独立的 mesh 对象。

模型导出与压缩

为了在 Web 端使用,我们需要将 Blender 文件导出为 GLB 格式,并使用 Draco 压缩:

# export_cli.py - Blender 命令行导出脚本import bpy # 选择所有肌肉相关的对象 muscle_keywords =['muscle','deltoid','bicep','tricep','pectoralis',...]for obj in bpy.data.objects:if obj.type=='MESH': name_lower = obj.name.lower()ifany(keyword in name_lower for keyword in muscle_keywords): obj.select_set(True)# 导出为 GLB,启用 Draco 压缩 bpy.ops.export_scene.gltf( filepath='muscle-anatomy.glb', export_format='GLB', use_selection=True, export_draco_mesh_compression_enable=True, export_draco_mesh_compression_level=6,)

导出后的模型从 300MB 压缩到约 6.8MB,非常适合 Web 加载。

核心实现

1. 场景搭建 (React Three Fiber)

// muscle-scene.tsx import { Canvas } from '@react-three/fiber'; import { OrbitControls, Environment } from '@react-three/drei'; export function MuscleScene({ onMuscleClick, onMuscleHover, hoveredMuscle, selectedMuscle }) { return ( <Canvas camera={{ position: [1.5, 0.3, 2], fov: 50 }}> {/* 环境光照 */} <ambientLight intensity={0.6} /> <directionalLight position={[5, 5, 5]} intensity={0.8} /> {/* 3D 模型 */} <Suspense fallback={null}> <MuscleModel onMuscleClick={onMuscleClick} onMuscleHover={onMuscleHover} hoveredMuscle={hoveredMuscle} selectedMuscle={selectedMuscle} /> </Suspense> {/* 轨道控制器 */} <OrbitControls enablePan={false} minDistance={1} maxDistance={5} target={[0, 0.5, 0]} /> {/* 环境贴图 */} <Environment preset="studio" /> </Canvas> ); } 

2. 模型加载与肌肉识别

// muscle-model.tsx import { useGLTF } from '@react-three/drei'; import * as THREE from 'three'; // 肌肉识别关键词 const muscleKeywords = [ 'muscle', 'deltoid', 'bicep', 'tricep', 'pectoralis', 'latissimus', 'trapezius', 'rectus', 'oblique', 'gluteus', 'quadricep', 'vastus', 'hamstring', 'gastrocnemius', 'soleus', // ... 更多关键词 ]; // 需要隐藏的非肌肉对象 const HIDDEN_KEYWORDS = [ 'region', 'fascia', 'bursa', 'ligament', 'membrane', '.j', '.t', // Z-Anatomy 的标签后缀 ]; function isMuscle(name: string): boolean { const lowerName = name.toLowerCase(); return muscleKeywords.some(keyword => lowerName.includes(keyword)) && !HIDDEN_KEYWORDS.some(keyword => lowerName.includes(keyword)); } export function MuscleModel({ onMuscleClick, onMuscleHover, hoveredMuscle, selectedMuscle }) { const { scene } = useGLTF('/models/muscle-anatomy.glb'); // 克隆场景并处理材质 const clonedScene = useMemo(() => { const clone = scene.clone(true); clone.traverse((child) => { if (child instanceof THREE.Mesh) { if (shouldHide(child.name)) { child.parent?.remove(child); return; } if (isMuscle(child.name)) { // 为肌肉设置红色系材质 child.material = child.material.clone(); child.material.color = new THREE.Color(0xc44d4d); child.material.roughness = 0.7; child.material.metalness = 0.1; } } }); return clone; }, [scene]); return ( <primitive object={clonedScene} position={[0, -0.84, 0]} onPointerOver={handlePointerOver} onPointerOut={handlePointerOut} onClick={handleClick} /> ); } 

3. 交互高亮效果

// 高亮颜色配置 const HIGHLIGHT_COLOR = new THREE.Color(0x5ac57a); // 薄荷绿 - 悬停 const SELECTED_COLOR = new THREE.Color(0x4caf50); // 深绿 - 选中 // 更新高亮效果 useEffect(() => { clonedScene.traverse((child) => { if (child instanceof THREE.Mesh && isMuscle(child.name)) { const material = child.material as THREE.MeshStandardMaterial; const muscleId = getMuscleIdFromModelName(child.name); const isHovered = muscleId === hoveredMuscle; const isSelected = muscleId === selectedMuscle; if (isSelected) { material.emissive = SELECTED_COLOR; material.emissiveIntensity = 0.5; } else if (isHovered) { material.emissive = HIGHLIGHT_COLOR; material.emissiveIntensity = 0.3; } else { material.emissive = new THREE.Color(0x000000); material.emissiveIntensity = 0; } } }); }, [hoveredMuscle, selectedMuscle, clonedScene]); 

4. 肌肉名称映射与多语言

Z-Anatomy 的命名格式是 Muscle name.l(左侧)/ Muscle name.r(右侧),我们需要将其映射到标准的肌肉 ID:

// muscles.tsconst muscleAliases: Record<string,string[]>={'pectoralis_major':['pectoralis major','sternocostal head of pectoralis major','clavicular head of pectoralis major',],'biceps_brachii':['biceps brachii','long head of biceps brachii','short head of biceps brachii',],// ... 更多映射};exportfunctiongetMuscleIdFromModelName(modelName:string):string|undefined{const cleanName = modelName .replace(/\.(l|r|el|er)$/i,'')// 移除左右后缀.toLowerCase().trim();for(const[muscleId, aliases]of Object.entries(muscleAliases)){if(aliases.some(alias => cleanName.includes(alias))){return muscleId;}}returnundefined;}

多语言翻译存储在 i18n 模块中:

// locales/zh/muscle-anatomy.tsexportconst muscleAnatomy ={ muscles:{ pectoralis_major:'胸大肌', biceps_brachii:'肱二头肌', triceps_brachii:'肱三头肌', latissimus_dorsi:'背阔肌', rectus_abdominis:'腹直肌', gluteus_maximus:'臀大肌', quadriceps_femoris:'股四头肌', gastrocnemius:'腓肠肌',// ... 150+ 肌肉翻译},};

性能优化

1. 模型压缩

  • 使用 Draco 压缩,模型从 300MB 压缩到 6.8MB
  • 在 Blender 中使用 Decimate Modifier 降低面数

2. 动态加载

// 使用 Next.js 动态导入,禁用 SSR const MuscleScene = dynamic( () => import('./muscle-scene').then((mod) => mod.MuscleScene), { ssr: false } ); 

3. 材质优化

  • 克隆材质避免全局修改
  • 使用 emissive 属性实现高亮,避免重新创建材质

应用场景

这套技术方案可以应用于多种场景:

  1. 健身教育:帮助健身爱好者了解肌肉位置和名称
  2. 医学教学:辅助医学生学习人体解剖
  3. 康复指导:展示特定肌肉群的位置
  4. 游戏开发:角色肌肉系统参考

如果你对健身相关的工具感兴趣,可以看看这些在线计算器:

总结

本文介绍了如何在前端使用 Three.js + React Three Fiber 实现交互式3D人体肌肉解剖展示。核心技术点包括:

  1. 模型处理:从 Z-Anatomy 导出并压缩 GLB 模型
  2. 场景搭建:使用 React Three Fiber 构建 3D 场景
  3. 交互实现:射线检测 + 材质高亮
  4. 多语言支持:肌肉名称中英文翻译

这套方案完全在浏览器端运行,无需后端服务,非常适合构建教育类的3D可视化应用。


相关链接:

Read more

FLUX.1-dev FP8完整部署教程:让6GB显存显卡也能玩转AI绘画

FLUX.1-dev FP8完整部署教程:让6GB显存显卡也能玩转AI绘画 【免费下载链接】flux1-dev 项目地址: https://ai.gitcode.com/hf_mirrors/Comfy-Org/flux1-dev 还在为显卡配置不够而苦恼吗?🤔 FLUX.1-dev FP8版本的出现彻底改变了游戏规则!这款革命性的量化模型将显存需求从16GB大幅降低至仅6GB,让RTX 3060、4060等主流显卡也能流畅运行专业级AI绘画,为普通用户打开了无限创意的大门。 🎯 为什么选择FLUX.1-dev FP8版本? 突破性的量化技术让中端显卡也能享受顶级AI绘画体验!通过智能分层量化策略,在保持核心功能精度的同时,实现了显著的性能提升。无论你是设计师、内容创作者还是AI爱好者,这款模型都能满足你的创作需求。 核心优势一览 * 显存需求降低60%:从16GB降至6GB * 兼容性全面提升:支持RTX 3060、4060等主流显卡 * 画质几乎无损:智能量化确保关键组件精度 * 部署简单快捷:完整教程带你从零开始 🛠️ 环境准备与项目获取 第一步

二次元AI绘画工具实战指南:从入门到进阶

本文面向想要使用AI工具生成二次元风格图像的开发者和创作者,从工具选择、环境配置、提示词工程到进阶技巧,提供一份完整的实战指南。 一、主流工具技术栈对比 目前二次元AI绘画主要有以下几种技术路线: 1.1 Stable Diffusion 本地部署 技术架构:基于Latent Diffusion Model,开源可本地运行 硬件要求: * GPU:NVIDIA显卡,8GB+显存(推荐12GB+) * 内存:16GB+ * 存储:50GB+(模型文件较大) 常用界面: * WebUI(AUTOMATIC1111):功能全面,插件生态丰富 * ComfyUI:节点式工作流,适合复杂流程编排 二次元常用模型: * Anything系列:经典二次元模型 * Counterfeit:高质量动漫风格 * MeinaMix:细节丰富的二次元模型 优势:可高度定制,隐私性好,技术上限高 劣势:配置门槛高,

基于腾讯云云服务器搭建一个Clawdbot,实现Telegram机器人自动回复

基于腾讯云云服务器搭建一个Clawdbot,实现Telegram机器人自动回复

哈咯大家好,这里依然是码农的搬运工!! 从25年开始,全球都开始走向AI,拥抱AI。 最近博主,也就是我,发现一个国外作者,【Peter Steinberger】在本月推出了一个新的智能体【Clawdbot】,首先我们可以先去官网看一下这个东西是什么:Clawdbot  那么我也是研究了一把,但是这个文档实在是差点把我这个大专生劝退,纯英文,废了九牛二虎之力,我才差不多看懂了。肯定有小伙伴比较好奇,那么文档给你们放出来你们也可以看看:https://docs.molt.bot/start/getting-started OK!话不多说,那我们开始实操一下: 首先呢,看了一下这个文档,安装环境还是不错的,macOS/Linux、Windows【Powershell/CMD】 而且作者还贴心的给了安装命令,这样就省了好大一部分精力。不需要费劲去git拉取代码编译了。【这里需要注意一点,macos系统得14+,作者只有13的系统,所以是没有办法弄mac的】 当然,如果有小伙伴就是头铁,还是想从git上拉代码,那我也给你贴一下这个文档,你来安装:

专访国外爆火的AI渗透机器人XBOW:对抗性机器人与自主威胁猎手的较量

专访国外爆火的AI渗透机器人XBOW:对抗性机器人与自主威胁猎手的较量

AI黑客永不休眠——我们的防御体系也不能停歇 数字孪生技术有望帮助我们实现全天候威胁追踪,先发制人地发现潜在威胁。 在最近的SecTor大会上,我发表了关于主动威胁追踪的演讲,随后在展区引发了一系列深入讨论。置身于众多"AI优先"安全厂商的展台之间,与我交谈的CISO(首席信息安全官)和威胁猎手们都流露出担忧。他们担心AI技术会将脚本小子(script kiddies)武装成具备高级能力的精英黑客,催生出大量对抗性AI机器人——而当前我们尚未做好应对准备。 虽然AI在网络安全领域确实具有巨大潜力,但现实中其主要用途仍是自动化现有流程。企业若想获得竞争优势,需要的不是优化现有方案,而是全新的AI驱动防御策略。 攻防不对称困境 攻击者本就具备系统性优势,而AI技术更将其无限放大。尽管存在诸多AI防御的成功案例,但这些技术若被恶意利用,后果将不堪设想。以初创公司XBOW开发的同名自主渗透测试机器人为例:这款安全产品表现卓越,今年夏天更创下漏洞悬赏平台HackerOne的历史记录——其自主渗透测试系统连续数月占据排行榜首位。 值得注意的是,虽然渗透测试完全由机器人完成,但人类仍在