如何在纯前端中通过手势交互来控制星球的转动

如何在纯前端中通过手势交互来控制星球的转动

技术栈

  • MediaPipe Hands - Google 的开源手部追踪库
  • Three.js - 3D 渲染引擎
  • 摄像头实时视频流输入

项目地址粒子土星


手势交互核心实现流程

步骤0:CDN导入

html 复制代码
<!-- MediaPipe 核心库 -->
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/hands/hands.js"></script>

<!-- Three.js (如果需要3D渲染) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

步骤1: 初始化手势检测器

js 复制代码
const hands = new Hands({
  locateFile: (file) => {
    return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
  }
});

hands.setOptions({
  maxNumHands: 1,           // 只检测一只手
  modelComplexity: 1,       // 模型复杂度(0-1)
  minDetectionConfidence: 0.7,  // 检测置信度阈值
  minTrackingConfidence: 0.7    // 追踪置信度阈值
});

步骤2: 启动摄像头并持续检测

js 复制代码
const cameraUtils = new Camera(videoElement, {
  onFrame: async () => {
    await hands.send({ image: videoElement });  // 每帧都发送给模型分析
  },
  width: 640,
  height: 480
});
cameraUtils.start();

步骤3: 处理检测结果 - 两个关键手势映射

🤏 手势1: 缩放控制 (拇指+食指距离)
js 复制代码
// 获取拇指尖端(landmark 4)和食指尖端(landmark 8)
const p1 = hand[4];  // 大拇指指尖
const p2 = hand[8];  // 食指指尖

// 计算两点间的欧氏距离
const dist = Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);

// 归一化到 [0, 1] 区间,然后映射到缩放范围 [0.15, 2.5]
const normDist = Math.max(0, Math.min(1, (dist - 0.02) / 0.25));
targetScale = 0.15 + normDist * 2.35;

效果 : 👌捏合手指 = 缩小 | ✋张开手指 = 放大

✋ 手势2: 俯仰角控制 (手掌Y轴位置)
复制代码
// 使用手腕位置(landmark 9)的Y坐标
const y = hand[9].y;  // 手掌中心点

// 归一化Y坐标到 [0, 1],映射到旋转角度 [-0.6, 1.0] 弧度
const normY = Math.max(0, Math.min(1, (y - 0.1) / 0.8));
targetRotX = -0.6 + normY * 1.6;

效果 : 🖐️手掌上移 = 向上看 | 🖐️手掌下移 = 向下看

项目中其他方面设计

平滑动画系统

为了让动作不卡顿,使用了 线性插值(Lerp) :

复制代码
const lerpFactor = 0.08;  // 插值系数,越小越平滑
currentScale += (targetScale - currentScale) * lerpFactor;
currentRotX += (targetRotX - currentRotX) * lerpFactor;

自动巡航模式

当没有检测到手时,进入自动巡航:

js 复制代码
if (!isHandDetected) {
  autoIdleTime += 0.005;
  targetScale = 1.0 + Math.sin(autoIdleTime) * 0.2;      // 自动缩放呼
  吸效果
  targetRotX = 0.4 + Math.sin(autoIdleTime * 0.3) * 0.15; // 自动轻微摇
  摆
}

Shader中的实际应用

手势控制的值最终传递给GPU着色器:

js 复制代码
uniforms.uScale.value = currentScale;      // 控制土星大小
uniforms.uRotationX.value = currentRotX;   // 控制视角俯仰

在GLSL着色器中应用旋转:

js 复制代码
// 处理整体视角的 X 轴旋转(即手势控制的俯仰角)
float cx = cos(uRotationX);
float sx = sin(uRotationX);
float ry = pos.y * cx - pos.z * sx;
float rz = pos.y * sx + pos.z * cx;
pos.y = ry;
pos.z = rz;

作者 :NotSleeply | 项目地址粒子土星

相关推荐
憧憬成为web高手5 小时前
ACTF 12307复现
前端·bootstrap·html
wordbaby6 小时前
Axios 上传大文件崩溃:鸿蒙 RNOH 下 XHR 返回空响应头引发的"假失败"
前端·react native
wordbaby6 小时前
React Native 列表分页实战:下拉刷新与上拉加载的工程化方案
前端·react native
wordbaby7 小时前
脱离 Tab 栏的艺术:React Native 全屏子页面的导航架构实践
前端·react native·harmonyos
陈随易7 小时前
Redis 8.8发布,一定要更新
前端·后端·程序员
wordbaby7 小时前
React Native 新架构落地鸿蒙:跨三端政务级应用的工程实践与深度复盘
前端·react native·harmonyos
excel9 小时前
为什么我推荐使用 Termius:现代 SSH 工具的完整体验
前端·后端
ZC跨境爬虫9 小时前
模块化烹饪小程序开发日记 Day7:(菜谱详情接口开发与JSON数据读取全流程)
前端·javascript·css·ui·微信小程序·json
এ慕ོ冬℘゜9 小时前
JS 前端基础面试题
开发语言·前端·javascript
LaughingZhu9 小时前
Product Hunt 每日热榜 | 2026-05-25
前端·人工智能·经验分享·chatgpt·html