基于canvas和three.js实现音频可视化三

前言
在数字化时代,我们正在见证音乐和视觉艺术的深度融合。流行音乐图像化,即将音乐视觉化,成为了一种独特的艺术表达方式。它跨越了时间和空间,用视觉元素诠释音乐的情感和氛围,为听众带来全新的感官体验。
今天分享的是一个基于WebAudio、canvas、three.js实现的简易音乐播放器。由于篇幅过长,所以分为三篇文章进行讲解。该篇文章主要叙述通过trree.js实现3d音频可视化。
音乐播放功能实现请查看 基于canvas和three.js实现音频可视化一
canvas音频可视化效果请查看 基于canvas和three.js实现音频可视化二

先来看下一最终效果:
在这里插入图片描述

实现简介

本篇文章主要讲述使用three.js实现音频可视化。在此之前你需要掌握three.js基本使用方法。

功能实现分为以下几个步骤:

  1. 添加html标签,设置css样式
  2. 初始化场景、相机、渲染器,添加光源、实体。
  3. 根据音频每一帧数据实现实体动画

1. 添加html标签,设置宽高和css样式

html代码

 <van-swipe-item>
 	<div class="threeContainer" ref="threeContainerRef"></div>
 </van-swipe-item>

css样式

.threeContainer {
  width: 100%;
  height: 400px;
}

2. 初始化场景、相机、渲染器,添加光源、添加实体

新建threeMusic.js文件,引入three.js,初始化变量,新建场景、相机、渲染器,添加光源、添加实体,具体实现请看代码

import * as THREE from './js/three.js'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

let audioContextOrigin, requestID = null;


const LENGTH = 240
const STEP = 12; // 定义步长
const CUBE_NUM = Math.ceil(LENGTH / STEP); // 要创建的长方体个数

const width = window.innerWidth;
const height = 500;

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 3000);

const renderer = new THREE.WebGLRenderer();

/**
 * 频谱立方体分组
 */
const cubes = new THREE.Group();

function create(parentDom) {
	// 设置灯光效果
    const pointLight = new THREE.PointLight( 0xffffff );
    pointLight.position.set(0, 300, 40);
    scene.add(pointLight);

    const pointLight1 = new THREE.PointLight( 0xffffff );
    pointLight1.position.set(-30, 30, 40);
    scene.add(pointLight1);
    
    const pointLight2 = new THREE.PointLight( 0xffffff );
    pointLight2.position.set(30, -30, 40);
    scene.add(pointLight2);

    const pointLight3 = new THREE.PointLight( 0xffffff );
    pointLight2.position.set(-30, -30, 40);
    scene.add(pointLight2);
	// 设置相机视角位置
    camera.position.set(0,100, 1000);
    camera.lookAt(scene.position);

    renderer.setSize(width, height);
    parentDom.appendChild(renderer.domElement)

    renderer.render(scene, camera)
	// 创建初始长方体
    for (let i = 0; i < CUBE_NUM; i ++ ) {
    	// 长方体初始大小长、宽、高都为10
        const geometry = new THREE.BoxGeometry( 10, 10, 10 );
        const material = new THREE.MeshBasicMaterial({color: 'yellowgreen'});
        const cube = new THREE.Mesh( geometry, material );
        // 长方体间距为10,坐标位置为长方体宽度10加上间距10 乘以索引
        cube.translateX((10 + 10) * i);
        cube.translateY(1);

        cubes.add(cube);
    }
    // 整体向x轴负半轴移动一半距离
    cubes.translateX(- (10 +10) * CUBE_NUM / 2);
    scene.add(cubes);
}

const controls = new OrbitControls(camera, renderer.domElement);

3、根据音频每一帧数据实现实体动画

新增长方体大小控制方法,新增控制动画类

function render() {
	// 获取音频数据
    let frequencyData = audioContextOrigin.byteFrequencyDate
    // 截取长度为240
    frequencyData = frequencyData.slice(0, LENGTH)
    const averageFrequencyData = [];
     // 12条数据累加作为一条数据
    for (let i = 0; i< frequencyData.length; i += STEP) {
        let sum = 0;
        for(let j = i; j < i + STEP; j++) {
            sum += frequencyData[j];
        }
        averageFrequencyData.push(sum / STEP);
    }
    // 长方体更具音频数据y轴动态设置放大比例
    for (let i = 0; i < averageFrequencyData.length; i++) {
      const scaleY = Math.floor(averageFrequencyData[i] * 0.2)
      scaleY && (cubes.children[i].scale.y = scaleY);
    }
    renderer.render(scene, camera);
	// 根据浏览器频率渲染
    requestID = requestAnimationFrame(render);
}

export class StartMusic{
  constructor(data = {
    audioContextOrigin: null,
    canvasDom: null,
  }) {
    audioContextOrigin = data.audioContextOrigin
    if (!audioContextOrigin) {
      throw new Error('缺少音乐数据源')
    }
    if (!data.canvasDom) {
      throw new Error('缺少渲染dom')
    }
    create(data.canvasDom);
    this.play()
  }
  play() {
    render();
  }
  paused() {
    cancelAnimationFrame(requestID);
  }
}

更新watch方法

 watch: {
    isbtnShow: {
      handler(val) {
        if (!val) {
          this.$nextTick(() => {
            this.initMusicEffect();
            this.initMusicThree()
          });
        }
         else {
          if (this.musicEffect) {
            this.musicEffect.paused();
          }
          if (this.musicThree) {
            this.musicThree.paused();
          }
        }
      },
      immediate: true
    }
  },

methods新增方法

 // three.js实现3d音频可视化
 initMusicThree() {
    if (!this.musicOriginData) {
      this.initMusicOrigin()
    }
    if (this.musicThree) {
      this.musicThree.play()
    } else {
      this.musicThree = new StartMusic({
        audioContextOrigin: this.musicOriginData,
        canvasDom: this.$refs.threeContainerRef
      })
    }
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值