使用react+three做一个动态音乐播放按钮

前言

最近在自学three,看见一个动态曲线的动图,就想着用three实现出来。

最终效果
在这里插入图片描述

主要技术栈
react

@react-three/fiber
@react-three/fiber 是一个 React renderer for Three.js,它允许你使用 React 的语法和组件化特性来构建 3D 场景。它是与 Three.js 交互的基础层,提供了以下功能:

  • React 集成:使 Three.js 的场景和对象可以像 React 组件那样使用。
  • 性能优化:利用 React 的虚拟 DOM 和变更检测机制来提高渲染效率。
  • Hooks 支持:支持 React Hooks,如 useFrame 和 useLoader。
  • 自动卸载:当组件不再被使用时,自动清理 Three.js 对象以避免内存泄漏。

@react-three/drei
@react-three/drei 是建立在 @react-three/fiber 之上的一个实用库,提供了许多常用的组件和工具,旨在简化常见的 3D 开发任务。这些工具通常包括但不限于:

  • 实用组件:如 OrbitControls, Suspense, Grid, Spotlight 等。
  • 加载器:用于加载纹理、模型和其他资源。
  • 辅助工具:如 useGLTF, useTexture 等。

代码

小玩意,我就直接贴代码,看下注释应该能懂了

'use client';
import React, { useState, useCallback, useContext } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { Line } from '@react-three/drei';
import { AudioContext } from '../lib/contexts/AudioContext';

// 用于绘制动态曲线的组件
function DynamicCurve() {
  const [curvePoints, setCurvePoints] = useState([]);

  // 在每个帧更新曲线点的位置
  // 更新曲线点的位置
  useFrame(({ clock }) => {
    const time = clock.getElapsedTime();
    const newCurvePoints = [];
    // 根据时间计算曲线上各点的位置
    for (let i = 0; i < 40; i++) {
      const x = i / 10 - 2;
      const y = Math.sin(3 * time + i / 10);
      const z = 0;
      newCurvePoints.push([x, y, z]);
    }

    // 更新曲线的点
    setCurvePoints(newCurvePoints);
  });

  if (curvePoints.length === 0) {
    return null; // 如果 curvePoints 为空,则返回 null,以防止渲染线条
  }

  return (
    <Line
      points={curvePoints}
      color="#fff"
      lineWidth={2}
      // 曲线的其他属性和样式
    />
  );
}

// 暂停状态下显示的静态直线组件
const StaticLine = () => (
  <Line
    points={[
      [-2, 0, 0],
      [2, 0, 0],
    ]}
    color="#fff"
    lineWidth={2}
  />
);

/**
 * 背景音乐按钮组件,用于控制背景音乐的播放和暂停,并显示当前播放状态。
 */
const BackgroundMusicButton = () => {
  // 这里我是因为做了个loader加载组件,网站加载完成之后可以选择有声进入还是无声进入
  const { isPlaying, play, pause } = useContext(AudioContext);

  // 使用useCallback优化播放/暂停函数的性能
  // 使用useCallback缓存函数
  const togglePlay = useCallback(() => {
    if (isPlaying) {
      pause();
    } else {
      play();
    }
  }, [isPlaying]);

  return (
    <div className="bg-button">
      <button onClick={togglePlay}>
        <Canvas frameloop="demand">
          {isPlaying ? <DynamicCurve /> : <StaticLine />}
        </Canvas>
      </button>
    </div>
  );
};

export default BackgroundMusicButton;

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值