ToB企服应用市场:ToB评测及商务社交产业平台

标题: 如何在前端网页实现live2d的动态效果 [打印本页]

作者: 天津储鑫盛钢材现货供应商    时间: 2024-8-18 01:31
标题: 如何在前端网页实现live2d的动态效果
React如何在前端网页实现live2d的动态效果

业务需求:
因为公司必要做机器人相干的业务,主要是谈天形式的内容,所以必要一个假造的卡通形象。而且为了更直观的展示用户和机器人对话的状态,该live2d动画的嘴型必要根据播放的内容来动。
相干技能原理:

1. 网页上使用live2d的相干技能原理

Live2D是一种先辈的技能,它允许艺术家和开发者创建具有高度表现力的二维脚色动画。这些脚色可以根据用户的交互进行动态相应,从而提供一种非常生动和吸引人的用户体验。Live2D广泛应用于游戏、假造偶像、广告和移动应用程序中。
Live2D由日本Cybernoids公司开发,旨在创造出能够进行平滑动作和心情变化的二维脚色,而不必要传统的帧动画。这是通过对二维图像进行切割和变形来实现的,使得脚色能够以看似三维的方式移动和表达情感。
2. 笔墨转语音 TTS

本项目使用的是讯飞的TTS在线笔墨转语音功能。使用Websocket实现客户端和讯飞服务器之间的通讯。总体逻辑就是客户端把必要播报的笔墨发送给讯飞的服务端,服务端颠末处置惩罚后,把笔墨转成了二进制的音频流返回给客户端,然后客户端使用适当的方法播放解析后的音频数据,完成从笔墨到语音的整个过程。
不过这项功能不是本次的内容的重点,另外详解。
3. 语音转笔墨 IAT

不是本次的内容的重点,另外详解。
项目实现

1. 引入live2d相干库

Cubism Web是一个基于Web技能的软件开发工具包,用于创建Live2D。Cubism Web提供了一组工具和库,使开发职员可以轻松地将Live2D模子集成到Web应用程序中。它支持多种平台和框架,包罗HTML5、JavaScript和CSS,因此可以在各种设备和浏览器上运行。
官网如下:
https://www.live2d.com/zh-CHS/sdk/download/web/
下载Cubism SDK文件:

解压后的目录如下,此中Core焦点库和Framework框架库是我们所必要的。

将上述展示的Core文件夹复制到项目标public文件下。

同时,在public文件夹下面的index.html中加上如下代码:
  1. <script src = "%PUBLIC_URL%/Core/live2dcubismcore.js"></script>
复制代码

同理,将上述展示的Framework移动到项目标src文件夹下。注意不是pubilc文件夹下了。直接放到src文件夹即可,或者其他目录也行,引用的时候知道地点就行。

Resources文件夹下放的是live2d的模子,具体模子的内容可以去官网下载简单的Model,也可以根据必要找计划师去计划你必要的Modal。笔者这边只是展示了项目里面一个Modal里面的内容。

官方提供的Modal地点:
https://www.live2d.com/zh-CHS/sdk/download/web/
以上文件预备好后,可以做页面渲染相干的工作了。根据官方给的Demo,如下图所示:

根据Demo中main.ts中的样例可以推断出,这段代码用于实现Live2D模子的初始化、渲染和相应浏览器事件。

  1. /**
  2. * Copyright(c) Live2D Inc. All rights reserved.
  3. *
  4. * Use of this source code is governed by the Live2D Open Software license
  5. * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
  6. */
  7. import { LAppDelegate } from './lappdelegate';
  8. import * as LAppDefine from './lappdefine';
  9. import { LAppGlManager } from './lappglmanager';
  10. /**
  11. * ブラウザロード後の処理
  12. */
  13. window.addEventListener(
  14.   'load',
  15.   (): void => {
  16.     // Initialize WebGL and create the application instance
  17.     if (
  18.       !LAppGlManager.getInstance() ||
  19.       !LAppDelegate.getInstance().initialize()
  20.     ) {
  21.       return;
  22.     }
  23.     LAppDelegate.getInstance().run();
  24.   },
  25.   { passive: true }
  26. );
  27. /**
  28. * 終了時の処理
  29. */
  30. window.addEventListener(
  31.   'beforeunload',
  32.   (): void => LAppDelegate.releaseInstance(),
  33.   { passive: true }
  34. );
  35. /**
  36. * Process when changing screen size.
  37. */
  38. window.addEventListener(
  39.   'resize',
  40.   () => {
  41.     if (LAppDefine.CanvasSize === 'auto') {
  42.       LAppDelegate.getInstance().onResize();
  43.     }
  44.   },
  45.   { passive: true }
  46. );
复制代码
而我们必要做的,则是把Demo中除了main.ts的其他文件Copy到项目中在自有的项目中,Render的相干目录如图所示:

2. 用React转写main.ts

然后main.ts实现的逻辑,用React的方式进行重构,在index.js中。本文只展示核定代码,因为实际情况会根据需求,增长很多其他的业务实现代码,好比笔者最初的需求是增长live2d的收听、播放等动画效果,所以必要额外传入sourceBuffer等数据。

  1. import React, { useEffect, useRef, useMemo, useCallback } from 'react';
  2. import AudioRMS from '@/utils/AudioProcess';
  3. import { Button } from 'antd-mobile';
  4. import { LAppDelegate } from './live2dConfig/lappdelegate';
  5. import { LAppLive2DManager } from './live2dConfig/lapplive2dmanager';
  6. import * as LAppDefine from './live2dConfig/lappdefine';
  7. import './index.css';
  8. function ReactLive2d(props, ref) {
  9.   const { width, height, audioContext, source, live2dModelId, isTTSPlaying } = props;
  10.   const rmsRef = useRef(null);
  11.   // setModelDir()用于根据外部传的Model Id动态的引入模型,如果没有这个需求可以就写死Model的逻辑即可
  12.   useEffect(() => {
  13.     // 根据外部传入的modelId,动态设置model
  14.     LAppDefine.lappdefineSet.setModelDir([live2dModelId]);
  15.     if (!navigator.userAgent.match(/mobile/i)) {
  16.       if (LAppDelegate.getInstance().initialize()) {
  17.         LAppDelegate.getInstance().run();
  18.       }
  19.     }
  20.     return () => {
  21.       rmsRef.current && rmsRef.current.destroy && rmsRef.current.destroy();
  22.       LAppDelegate.releaseInstance();
  23.     }
  24.   }, []);
  25.   const configRmsWithAudio = () => {
  26.     if (source) {
  27.       source.connect(rmsRef.current.input)
  28.     }
  29.   }
  30.   useEffect(() => {
  31.     configRmsWithAudio();
  32.   }, [audioContext, source])
  33.   const onData = useCallback((data) => {
  34.     LAppLive2DManager.getInstance().setRmsToValue(data[0])
  35.   }, []);
  36.   useEffect(() => {
  37.     if (audioContext) {
  38.       if (!rmsRef.current) {
  39.         rmsRef.current = AudioRMS(audioContext, 'sqr')
  40.       }
  41.       if (isTTSPlaying) {
  42.         rmsRef.current.on('data', onData)
  43.       } else {
  44.         rmsRef.current.off('data', onData)
  45.       }
  46.     }
  47.   }, [audioContext, isTTSPlaying, onData])
  48.   const canvasWidth = useMemo(() => {
  49.     if (!window.matchMedia("(orientation: landscape)").matches) {
  50.       return document.body.clientWidth;
  51.     }
  52.     return document.body.clientWidth * 0.3;
  53.   }, [])
  54.   const canvasHeight = useMemo(() => {
  55.     if (!window.matchMedia("(orientation: landscape)").matches) {
  56.       return document.body.clientHeight * 0.3;
  57.     }
  58.     return document.body.clientHeight * 0.6;
  59.   }, [])
  60.   return (
  61.     <div className='live2d-container' >
  62.       <div className='live2d-canvas'>
  63.         <canvas
  64.           id="live2d"
  65.           width={width ? width : canvasWidth}
  66.           height={height ? height : canvasHeight}
  67.           className="live2d"
  68.           color="#f5f5f9"
  69.         />
  70.       </div>
  71.     </div>
  72.   )
  73. }
  74. export default ReactLive2d;
复制代码
在上述代码通过React组件设置了一个元素,并通过Live2D的JavaScript API初始化和控制Live2D模子的加载、表现和动作,实现了在Web页面上展示Live2D动画形象的功能。
但是此中有些代码是根据实际业务增长的,不属于原本demo的逻辑,这边做一些简述,防止读者混淆。
  1. //
  2. const onData = useCallback((data) => {
  3.     LAppLive2DManager.getInstance().setRmsToValue(data[0])
  4.   }, []);
  5. // AudioRMS()用于处理音频的技术,实现音频信号的实时分析和处理
  6. // 这段代码的目的是在确认音频源 source 存在的情况下,将它连接到通过 rmsRef 引用的目标的 input 上。
  7. // 这样的操作在音频处理、音频可视化等场景中非常常见,比如连接一个音频源到一个用于计算实时音频信号强度的节点上。
  8.   useEffect(() => {
  9.     if (audioContext) {
  10.       if (!rmsRef.current) {
  11.         rmsRef.current = AudioRMS(audioContext, 'sqr')
  12.       }
  13.       if (isTTSPlaying) {
  14.         rmsRef.current.on('data', onData)
  15.       } else {
  16.         rmsRef.current.off('data', onData)
  17.       }
  18.     }
  19.   }, [audioContext, isTTSPlaying, onData])
  20. // 。它调用source的connect方法,将音频源连接到rmsRef.current.input。
  21. // 这里,rmsRef是一个引用(通过useRef创建),指向RMS处理器的实例,而rmsRef.current.input是RMS处理器的输入端。
  22.   const configRmsWithAudio = () => {
  23.     if (source) {
  24.       source.connect(rmsRef.current.input)
  25.     }
  26.   }
  27. // 这段代码的目的是确保每当音频上下文(audioContext)或音频源(source)发生变化时,都会更新音频源与RMS处理器之间的连接。
  28.   useEffect(() => {
  29.     configRmsWithAudio();
  30.   }, [audioContext, source])
复制代码
3. 引用

上述工作做完后,引用则变得很简单了。
  1. import ReactLive2d from '...'
  2. ...
  3. // 以下参数根据实际情况自行填写即可
  4.   <ReactLive2d
  5.     source={bufferSource}
  6.     live2dModelId={'LH1'}
  7.     isTTSPlaying={iatStatus === 'ttsPlaying'}
  8.     audioContext={ttsRecorder.audioContext}
  9.   />
  10.   }, [audioContext, source])
复制代码
3. 引用

上述工作做完后,引用则变得很简单了。
  1. import ReactLive2d from '...'
  2. ...
  3. // 以下参数根据实际情况自行填写即可
  4.   <ReactLive2d
  5.     source={bufferSource}
  6.     live2dModelId={'LH1'}
  7.     isTTSPlaying={iatStatus === 'ttsPlaying'}
  8.     audioContext={ttsRecorder.audioContext}
  9.   />
复制代码
然后运行引用<ReactLive2d/>的界面上,便可以看到live2d的效果。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4