Commit ee0a0731 authored by xiezhi's avatar xiezhi

Initial commit: Three.js 项目模板

- 包含完整的 Three.js 3D 场景应用
- 支持 9 种不同几何体和交互控制
- 完整的 Docker 容器化支持
- 标准化的 Makefile 构建脚本
- 环境变量配置支持
- 实时统计信息显示
parents
{
"version": "1.0.0",
"name": "Three.js 3D 场景应用",
"tags": ["javascript", "three.js", "3d", "webgl", "frontend"],
"description": "基于 Three.js 的 3D 场景应用,包含多种几何体、光照系统和交互控制",
"init_commands": ["make install"],
"start_commands": ["make run"],
"stop_commands": ["make stop"],
"mapping_ports": {
"APP_PORT_1": 8000,
"APP_PORT_2": 8001,
"APP_PORT_3": 8002,
"APP_PORT_4": 8003
},
"deploy": [
{
"image_name": "threejs-app",
"app_access_entry": true,
"ports": [
{
"name": "APP_PORT_1",
"main_port": true,
"inner_access_env_key": "WEB_URL",
"open_access": true,
"open_access_env_key": "WEB_DOMAIN"
}
],
"docker_file_dir": "./",
"deploy_resources": {
"cpu_limit": 0.5,
"memory_limit": 1,
"storage_limit": 1
}
}
]
}
# 依赖
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# 构建输出
dist/
build/
.next/
out/
# 环境变量
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# 日志
logs/
*.log
# 运行时数据
pids/
*.pid
*.seed
*.pid.lock
# 覆盖率目录
coverage/
.nyc_output/
# 依赖锁定文件(可选)
package-lock.json
yarn.lock
pnpm-lock.yaml
# IDE 和编辑器
.vscode/
.idea/
*.swp
*.swo
*~
# 操作系统
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# 临时文件
*.tmp
*.temp
# Docker
.dockerignore
{}
\ No newline at end of file
{}
\ No newline at end of file
# 使用 Node.js 22 官方镜像作为基础镜像
FROM hb.eazytec-cloud.com/eazytec/eazydevelop-node:ubuntu22.04-node22-latest
# 设置工作目录
WORKDIR /app
# 设置环境变量
ENV NODE_ENV=production
ENV PORT=${APP_PORT_1:-8000}
# 复制 package.json 和 package-lock.json(如果存在)
COPY package*.json ./
# 安装依赖
RUN npm ci
# 复制应用代码
COPY . .
# 创建非 root 用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S threejs -u 1001
# 更改文件所有权
RUN chown -R threejs:nodejs /app
USER threejs
# 暴露端口
EXPOSE ${APP_PORT_1:-8000}
# 设置启动脚本
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:${APP_PORT_1:-8000} || exit 1
# 启动应用
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["npm", "run", "serve"]
# Three.js 项目模板 Makefile
# 用于构建、运行 Three.js 应用
# 变量定义
APP_NAME = threejs-template
NODE_VERSION = 22
APP_PORT = $(or $(APP_PORT_1),8000)
LOG_FILE = $(abspath $(dir $(lastword $(MAKEFILE_LIST))))/.logs/app.log
PID_FILE = $(abspath $(dir $(lastword $(MAKEFILE_LIST))))/.logs/app.pid
RESOURCE_PATH = $(abspath $(dir $(lastword $(MAKEFILE_LIST))))/.resource/resource_dev.json
# Node.js命令
NODE = node
NPM = npm
# 默认目标
.DEFAULT_GOAL := install
# 安装命令
.PHONY: install
install:
@echo "🎨 初始化 Three.js 应用项目..."
@echo "检查 Node.js 版本..."
@$(NODE) --version
@echo "检查 NPM 版本..."
@$(NPM) --version
@echo "安装项目依赖..."
@if [ -f "package.json" ]; then \
$(NPM) install; \
echo "✅ 依赖安装完成"; \
else \
echo "❌ package.json 不存在"; \
exit 1; \
fi
@echo "✅ Three.js 应用项目安装完成!"
# 运行命令
.PHONY: run
run: install
@echo "🎨 启动 Three.js 应用服务器..."
@mkdir -p $(dir $(LOG_FILE))
@if [ -f "$(PID_FILE)" ]; then \
echo "服务器已在运行中,PID: $$(cat $(PID_FILE))"; \
exit 1; \
fi
@echo "构建项目..."
@$(NPM) run build
@echo "启动服务器在端口 $(APP_PORT)..."
@RESOURCE_PATH=$(RESOURCE_PATH) nohup $(NPM) run serve > $(LOG_FILE) 2>&1 & echo $$! > $(PID_FILE)
@sleep 3
@echo "✅ Three.js 应用服务器已启动,PID: $$(cat $(PID_FILE))"
@echo "🎯 应用访问地址: http://localhost:$(APP_PORT)/"
@echo "📋 查看日志: tail -f $(LOG_FILE)"
# 停止命令
.PHONY: stop
stop:
@echo "🛑 停止 Three.js 应用服务器..."
@if [ -f "$(PID_FILE)" ]; then \
PID=$$(cat $(PID_FILE)); \
if ps -p $$PID > /dev/null 2>&1; then \
echo "正在停止进程 $$PID..."; \
kill -TERM $$PID; \
sleep 2; \
if ps -p $$PID > /dev/null 2>&1; then \
echo "强制停止进程 $$PID..."; \
kill -9 $$PID; \
fi; \
echo "✅ 服务器已停止"; \
else \
echo "服务器进程不存在"; \
fi; \
rm -f $(PID_FILE); \
else \
echo "服务器未运行"; \
fi
# 清理命令
.PHONY: clean
clean:
@echo "🧹 清理 Three.js 应用项目文件..."
@rm -rf node_modules
@rm -rf .logs
@rm -rf dist
@rm -rf build
@rm -f package-lock.json
@echo "✅ 清理完成!"
# Three.js 项目模板
一个功能完整的 Three.js 项目模板,包含基础 3D 场景、光照系统、材质、交互控制和容器化部署支持。
## 🚀 特性
-**完整的 3D 场景**: 包含多种几何体、光照系统和材质
- 🎮 **交互控制**: 鼠标拖拽旋转、滚轮缩放、点击交互
- 🎨 **现代 UI**: 响应式设计,美观的加载动画和信息面板
- 📊 **实时统计**: FPS、物体数量、顶点数量实时显示
- 🐳 **容器化支持**: 完整的 Docker 配置和部署脚本
- 📱 **响应式设计**: 支持移动端和桌面端
- 🔧 **开发友好**: 完整的构建工具链和开发环境
## 📁 项目结构
```
three.js-template/
├── index.html # 主页面
├── main.js # Three.js 主逻辑
├── styles.css # 样式文件
├── package.json # 项目配置
├── Dockerfile # Docker 配置
├── docker-entrypoint.sh # Docker 启动脚本
├── Makefile # 构建脚本
└── README.md # 项目说明
```
## 🛠️ 技术栈
- **Three.js**: 3D 图形库
- **JavaScript ES6+**: 现代 JavaScript 语法
- **CSS3**: 现代样式和动画
- **Docker**: 容器化部署
- **Node.js**: 运行时环境
## 🚀 快速开始
### 方式一:本地开发
1. **克隆项目**
```bash
git clone <repository-url>
cd three.js-template
```
2. **安装依赖**
```bash
npm install
```
3. **启动开发服务器**
```bash
npm run dev
```
4. **访问应用**
打开浏览器访问 `http://localhost:5173`
### 方式二:Docker 部署
1. **构建镜像**
```bash
make docker-build
```
2. **运行容器**
```bash
make docker-run
```
3. **访问应用**
打开浏览器访问 `http://localhost:8000`
### 方式三:一键启动
```bash
make start
```
## 🎮 控制说明
| 操作 | 说明 |
|------|------|
| 鼠标左键拖拽 | 旋转视角 |
| 鼠标滚轮 | 缩放场景 |
| 鼠标右键拖拽 | 平移视角 |
| 点击物体 | 查看物体信息 |
## 📋 可用命令
### 开发命令
```bash
make install # 安装依赖
make dev # 启动开发服务器
make serve # 启动生产服务器
make build # 构建项目
make check # 检查项目状态
make lint # 代码检查
make test # 运行测试
```
### Docker 命令
```bash
make docker-build # 构建 Docker 镜像
make docker-run # 运行 Docker 容器
make docker-stop # 停止 Docker 容器
make docker-logs # 查看容器日志
make docker-shell # 进入容器 shell
```
### 部署命令
```bash
make deploy # 构建并部署
make restart # 重启容器
make status # 检查服务状态
make start # 快速启动
```
### 清理命令
```bash
make clean # 清理构建文件
make clean-docker # 清理 Docker 资源
make reset # 完全重置项目
```
## 🔧 自定义配置
### 修改端口
在 `package.json` 中修改启动脚本:
```json
{
"scripts": {
"serve": "python3 -m http.server 8000"
}
}
```
### 添加新的几何体
在 `main.js` 的 `createGeometry()` 方法中添加:
```javascript
{
type: 'your-geometry',
position: [x, y, z],
color: 0xhexcolor
}
```
### 自定义光照
在 `createLights()` 方法中修改光照参数:
```javascript
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(10, 10, 5);
```
## 📊 性能优化
### 几何体优化
- 使用 `BufferGeometry` 减少内存占用
- 合并相似几何体减少绘制调用
- 使用 LOD(细节层次)系统
### 材质优化
- 使用 `MeshBasicMaterial` 用于简单场景
- 合并材质减少状态切换
- 使用纹理压缩
### 渲染优化
- 启用视锥体剔除
- 使用遮挡剔除
- 合理设置阴影质量和范围
## 🐛 故障排除
### 常见问题
1. **依赖安装失败**
```bash
rm -rf node_modules package-lock.json
npm install
```
2. **Docker 构建失败**
```bash
docker system prune -a
make docker-build
```
3. **端口被占用**
```bash
# 查看端口占用
lsof -i :8000
# 杀死进程
kill -9 <PID>
```
### 性能问题
1. **帧率过低**
- 减少几何体复杂度
- 降低阴影质量
- 减少同时渲染的物体数量
2. **内存占用过高**
- 使用几何体合并
- 及时释放不需要的资源
- 使用纹理压缩
## 📚 学习资源
- [Three.js 官方文档](https://threejs.org/docs/)
- [Three.js 示例](https://threejs.org/examples/)
- [WebGL 基础教程](https://webglfundamentals.org/)
- [3D 数学基础](https://www.khanacademy.org/math/geometry-home)
## 🤝 贡献
欢迎提交 Issue 和 Pull Request 来改进这个模板!
## 📄 许可证
MIT License - 详见 [LICENSE](LICENSE) 文件
## 🎯 下一步
- [ ] 添加更多几何体类型
- [ ] 实现纹理加载
- [ ] 添加音频支持
- [ ] 实现场景切换
- [ ] 添加 VR/AR 支持
---
**享受 Three.js 开发的乐趣!** 🎉
#!/bin/bash
# Three.js 项目启动脚本
# 用于 Docker 容器启动时的环境配置和服务启动
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查 Node.js 版本
check_node_version() {
log_info "检查 Node.js 版本..."
node_version=$(node --version)
log_success "Node.js 版本: $node_version"
}
# 检查 npm 版本
check_npm_version() {
log_info "检查 npm 版本..."
npm_version=$(npm --version)
log_success "npm 版本: $npm_version"
}
# 检查项目依赖
check_dependencies() {
log_info "检查项目依赖..."
if [ ! -f "package.json" ]; then
log_error "package.json 文件不存在!"
exit 1
fi
if [ ! -d "node_modules" ]; then
log_warning "node_modules 目录不存在,正在安装依赖..."
npm install
fi
log_success "依赖检查完成"
}
# 检查必要文件
check_required_files() {
log_info "检查必要文件..."
required_files=("index.html" "main.js" "styles.css")
for file in "${required_files[@]}"; do
if [ ! -f "$file" ]; then
log_error "必要文件 $file 不存在!"
exit 1
fi
done
log_success "所有必要文件检查完成"
}
# 设置权限
set_permissions() {
log_info "设置文件权限..."
chmod -R 755 /app
log_success "权限设置完成"
}
# 创建日志目录
create_log_dir() {
log_info "创建日志目录..."
mkdir -p /app/logs
chmod 755 /app/logs
log_success "日志目录创建完成"
}
# 启动健康检查
start_health_check() {
log_info "启动健康检查..."
# 在后台启动健康检查
(
sleep 5
while true; do
if curl -f http://localhost:${APP_PORT_1:-8000} > /dev/null 2>&1; then
log_success "应用运行正常"
else
log_warning "应用可能未正常启动"
fi
sleep 30
done
) &
log_success "健康检查已启动"
}
# 显示启动信息
show_startup_info() {
echo ""
echo "=========================================="
echo " Three.js 项目模板启动成功!"
echo "=========================================="
echo ""
echo "🌐 访问地址: http://localhost:${APP_PORT_1:-8000}"
echo "📁 项目目录: /app"
echo "📊 Node.js: $(node --version)"
echo "📦 npm: $(npm --version)"
echo ""
echo "🎮 控制说明:"
echo " - 鼠标左键拖拽: 旋转视角"
echo " - 鼠标滚轮: 缩放"
echo " - 鼠标右键拖拽: 平移视角"
echo " - 点击物体: 查看信息"
echo ""
echo "=========================================="
echo ""
}
# 清理函数
cleanup() {
log_info "正在清理资源..."
# 这里可以添加清理逻辑
log_success "清理完成"
}
# 设置信号处理
trap cleanup EXIT INT TERM
# 主函数
main() {
log_info "开始启动 Three.js 项目..."
# 执行检查
check_node_version
check_npm_version
check_dependencies
check_required_files
set_permissions
create_log_dir
# 显示启动信息
show_startup_info
# 启动健康检查
start_health_check
log_success "Three.js 项目启动完成!"
# 执行传入的命令
exec "$@"
}
# 如果直接运行此脚本
if [ "${BASH_SOURCE[0]}" == "${0}" ]; then
main "$@"
fi
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js 项目模板</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="container">
<div id="loading">
<div class="loader"></div>
<p>正在加载 Three.js 场景...</p>
</div>
<div id="info">
<h1>Three.js 项目模板</h1>
<div id="controls">
<p>控制说明:</p>
<ul>
<li>鼠标左键拖拽:旋转视角</li>
<li>鼠标滚轮:缩放</li>
<li>鼠标右键拖拽:平移视角</li>
<li>点击物体:查看信息</li>
</ul>
</div>
<div id="stats">
<p>FPS: <span id="fps">0</span></p>
<p>物体数量: <span id="objects">0</span></p>
<p>顶点数量: <span id="vertices">0</span></p>
</div>
</div>
</div>
<!-- 使用 ES6 模块方式引入 Three.js -->
<script type="module" src="main.js"></script>
</body>
</html>
This diff is collapsed.
{
"name": "threejs-template",
"version": "1.0.0",
"description": "Three.js 项目模板,包含基础 3D 场景和交互功能",
"main": "main.js",
"engines": {
"node": ">=20.0.0"
},
"scripts": {
"dev": "vite --port ${APP_PORT_1:-5173}",
"build": "vite build",
"preview": "vite preview --port ${APP_PORT_1:-5173}",
"serve": "vite preview --port ${APP_PORT_1:-8000} --host 0.0.0.0"
},
"keywords": [
"three.js",
"3d",
"webgl",
"javascript",
"template"
],
"author": "Template Tool",
"license": "MIT",
"dependencies": {
"three": "0.160.0"
},
"devDependencies": {
"vite": "5.0.0",
"terser": "5.24.0"
}
}
/* 全局样式重置 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
overflow: hidden;
height: 100vh;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
/* 加载动画样式 */
#loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
color: white;
z-index: 1000;
}
.loader {
width: 50px;
height: 50px;
border: 5px solid #f3f3f3;
border-top: 5px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 信息面板样式 */
#info {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 20px;
border-radius: 10px;
backdrop-filter: blur(10px);
z-index: 100;
max-width: 300px;
font-size: 14px;
line-height: 1.6;
}
#info h1 {
margin-bottom: 15px;
color: #3498db;
font-size: 18px;
}
#controls ul {
list-style-type: none;
margin-top: 10px;
}
#controls li {
margin: 5px 0;
padding-left: 15px;
position: relative;
}
#controls li:before {
content: "•";
color: #3498db;
position: absolute;
left: 0;
}
/* 统计信息样式 */
#stats {
margin-top: 20px;
padding-top: 20px;
border-top: 1px solid rgba(255, 255, 255, 0.3);
}
#stats p {
margin: 5px 0;
display: flex;
justify-content: space-between;
}
#stats span {
color: #3498db;
font-weight: bold;
}
/* 响应式设计 */
@media (max-width: 768px) {
#info {
top: 10px;
left: 10px;
right: 10px;
max-width: none;
font-size: 12px;
padding: 15px;
}
#info h1 {
font-size: 16px;
}
}
/* Canvas 样式 */
canvas {
display: block;
cursor: grab;
}
canvas:active {
cursor: grabbing;
}
import { defineConfig } from 'vite'
/**
* Vite 配置文件
* 用于开发环境的热重载和构建优化
*/
export default defineConfig({
// 开发服务器配置
server: {
host: '0.0.0.0',
port: parseInt(process.env.APP_PORT_1) || 5173,
open: true,
cors: true
},
// 构建配置
build: {
outDir: 'dist',
assetsDir: 'assets',
sourcemap: true,
minify: 'terser',
rollupOptions: {
output: {
manualChunks: {
'three': ['three']
}
}
}
},
// 优化配置
optimizeDeps: {
include: ['three']
},
// 别名配置
resolve: {
alias: {
'@': '/src'
}
}
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment