|
@@ -49,6 +49,7 @@ import Plyr from "plyr";
|
|
|
import { Vue3Lottie } from "vue3-lottie";
|
|
|
import audioBga from "./images/audioBga.json";
|
|
|
import videobg from "./images/videobg.png";
|
|
|
+import audioVisualDraw from "./audioVisualDraw"
|
|
|
|
|
|
export default defineComponent({
|
|
|
name: 'creation-detail',
|
|
@@ -101,6 +102,7 @@ export default defineComponent({
|
|
|
})
|
|
|
const staffDom= ref<HTMLIFrameElement>()
|
|
|
const {playStaff, pauseStaff, updateProgressStaff} = staffMoveInstance()
|
|
|
+ let isInitAudioVisualDraw =false
|
|
|
// 点赞
|
|
|
const onStarChange = async () => {
|
|
|
await checkLogin();
|
|
@@ -171,20 +173,6 @@ export default defineComponent({
|
|
|
fullscreen: { enabled: false },
|
|
|
});
|
|
|
const player = state._plrl
|
|
|
- // 创建音波数据
|
|
|
- if(state.playType === "Audio"){
|
|
|
- const audioDom = document.querySelector("#audioMediaSrc") as HTMLAudioElement
|
|
|
- const canvasDom = document.querySelector("#audioVisualizer") as HTMLCanvasElement
|
|
|
- const { pauseVisualDraw, playVisualDraw } = audioVisualDraw(audioDom, canvasDom)
|
|
|
- player.on('play', () => {
|
|
|
- lottieDom.value.play()
|
|
|
- playVisualDraw()
|
|
|
- });
|
|
|
- player.on('pause', () => {
|
|
|
- lottieDom.value.pause()
|
|
|
- pauseVisualDraw()
|
|
|
- });
|
|
|
- }
|
|
|
// 在微信中运行的时候,微信没有开放自动加载资源的权限,所以要等播放之后才显示播放控制器
|
|
|
player.on('loadedmetadata', () => {
|
|
|
plyrState.loaded = true
|
|
@@ -221,112 +209,27 @@ export default defineComponent({
|
|
|
}
|
|
|
//点击改变播放状态
|
|
|
function handlerClickPlay(){
|
|
|
- if (state._plrl.playing) {
|
|
|
- state._plrl.pause();
|
|
|
- } else {
|
|
|
- state._plrl.play();
|
|
|
- }
|
|
|
- }
|
|
|
- /**
|
|
|
- * 音频可视化
|
|
|
- * @param audioDom
|
|
|
- * @param canvasDom
|
|
|
- * @param fftSize 2的幂数,最小为32
|
|
|
- */
|
|
|
- function audioVisualDraw(audioDom: HTMLAudioElement, canvasDom: HTMLCanvasElement, fftSize = 128) {
|
|
|
- type propsType = { canvWidth: number; canvHeight: number; canvFillColor: string; lineColor: string; lineGap: number }
|
|
|
- // canvas
|
|
|
- const canvasCtx = canvasDom.getContext("2d")!
|
|
|
- const { width, height } = canvasDom.getBoundingClientRect()
|
|
|
- canvasDom.width = width
|
|
|
- canvasDom.height = height
|
|
|
- // audio
|
|
|
- let audioCtx : AudioContext | null = null
|
|
|
- let analyser : AnalyserNode | null = null
|
|
|
- let source : MediaElementAudioSourceNode | null = null
|
|
|
- const dataArray = new Uint8Array(fftSize / 2)
|
|
|
- const draw = (data: Uint8Array, ctx: CanvasRenderingContext2D, { lineGap, canvWidth, canvHeight, canvFillColor, lineColor }: propsType) => {
|
|
|
- if (!ctx) return
|
|
|
- const w = canvWidth
|
|
|
- const h = canvHeight
|
|
|
- fillCanvasBackground(ctx, w, h, canvFillColor)
|
|
|
- // 可视化
|
|
|
- const dataLen = data.length
|
|
|
- let step = (w / 2 - lineGap * dataLen) / dataLen
|
|
|
- step < 1 && (step = 1)
|
|
|
- const midX = w / 2
|
|
|
- const midY = h / 2
|
|
|
- let xLeft = midX
|
|
|
- for (let i = 0; i < dataLen; i++) {
|
|
|
- const value = data[i]
|
|
|
- const percent = value / 255 // 最大值为255
|
|
|
- const barHeight = percent * midY
|
|
|
- canvasCtx.fillStyle = lineColor
|
|
|
- // 中间加间隙
|
|
|
- if (i === 0) {
|
|
|
- xLeft -= lineGap / 2
|
|
|
- }
|
|
|
- canvasCtx.fillRect(xLeft - step, midY - barHeight, step, barHeight)
|
|
|
- canvasCtx.fillRect(xLeft - step, midY, step, barHeight)
|
|
|
- xLeft -= step + lineGap
|
|
|
- }
|
|
|
- let xRight = midX
|
|
|
- for (let i = 0; i < dataLen; i++) {
|
|
|
- const value = data[i]
|
|
|
- const percent = value / 255 // 最大值为255
|
|
|
- const barHeight = percent * midY
|
|
|
- canvasCtx.fillStyle = lineColor
|
|
|
- if (i === 0) {
|
|
|
- xRight += lineGap / 2
|
|
|
- }
|
|
|
- canvasCtx.fillRect(xRight, midY - barHeight, step, barHeight)
|
|
|
- canvasCtx.fillRect(xRight, midY, step, barHeight)
|
|
|
- xRight += step + lineGap
|
|
|
- }
|
|
|
- }
|
|
|
- const fillCanvasBackground = (ctx: CanvasRenderingContext2D, w: number, h: number, colors: string) => {
|
|
|
- ctx.clearRect(0, 0, w, h)
|
|
|
- ctx.fillStyle = colors
|
|
|
- ctx.fillRect(0, 0, w, h)
|
|
|
- }
|
|
|
- const requestAnimationFrameFun = () => {
|
|
|
- requestAnimationFrame(() => {
|
|
|
- analyser?.getByteFrequencyData(dataArray)
|
|
|
- draw(dataArray, canvasCtx, {
|
|
|
- lineGap: 2,
|
|
|
- canvWidth: width,
|
|
|
- canvHeight: height,
|
|
|
- canvFillColor: "transparent",
|
|
|
- lineColor: "rgba(255, 255, 255, 0.7)"
|
|
|
- })
|
|
|
- if (!isPause) {
|
|
|
- requestAnimationFrameFun()
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- let isPause = true
|
|
|
- const playVisualDraw = () => {
|
|
|
- if (!audioCtx) {
|
|
|
- audioCtx = new AudioContext()
|
|
|
- source = audioCtx.createMediaElementSource(audioDom)
|
|
|
- analyser = audioCtx.createAnalyser()
|
|
|
- analyser.fftSize = fftSize
|
|
|
- source?.connect(analyser)
|
|
|
- analyser.connect(audioCtx.destination)
|
|
|
- }
|
|
|
- //audioCtx.resume() // 重新更新状态 加了暂停和恢复音频音质发生了变化 所以这里取消了
|
|
|
- isPause = false
|
|
|
- requestAnimationFrameFun()
|
|
|
- }
|
|
|
- const pauseVisualDraw = () => {
|
|
|
- isPause = true
|
|
|
- //audioCtx?.suspend() // 暂停 加了暂停和恢复音频音质发生了变化 所以这里取消了
|
|
|
- // source?.disconnect()
|
|
|
- // analyser?.disconnect()
|
|
|
+ const player = state._plrl;
|
|
|
+ // 由于ios低版本必须在用户操作之后才能初始化 createMediaElementSource 所以必须在用户操作之后初始化
|
|
|
+ if(!isInitAudioVisualDraw && state.playType === "Audio"){
|
|
|
+ isInitAudioVisualDraw = true
|
|
|
+ // 创建音波数据
|
|
|
+ const audioDom = document.querySelector("#audioMediaSrc") as HTMLAudioElement
|
|
|
+ const canvasDom = document.querySelector("#audioVisualizer") as HTMLCanvasElement
|
|
|
+ const { pauseVisualDraw, playVisualDraw } = audioVisualDraw(audioDom, canvasDom)
|
|
|
+ player.on('play', () => {
|
|
|
+ lottieDom.value.play()
|
|
|
+ playVisualDraw()
|
|
|
+ });
|
|
|
+ player.on('pause', () => {
|
|
|
+ lottieDom.value.pause()
|
|
|
+ pauseVisualDraw()
|
|
|
+ });
|
|
|
}
|
|
|
- return {
|
|
|
- playVisualDraw,
|
|
|
- pauseVisualDraw
|
|
|
+ if (player.playing) {
|
|
|
+ player.pause();
|
|
|
+ } else {
|
|
|
+ player.play();
|
|
|
}
|
|
|
}
|
|
|
function handlerLandscapeScreen(event:any){
|
|
@@ -430,8 +333,8 @@ export default defineComponent({
|
|
|
});
|
|
|
// 初始化五线谱
|
|
|
function initStaff(){
|
|
|
- const src = `${vaildMusicScoreUrl()}/instrument/#/simple-detail?id=${state.musicDetail.musicSheetId}&musicRenderType=${staffState.musicRenderType}&part-index=${staffState.partIndex}`;
|
|
|
- //const src = `https://dev.kt.colexiu.com/instrument/#/simple-detail?id=${state.musicDetail.musicSheetId}&musicRenderType=${staffState.musicRenderType}&part-index=${staffState.partIndex}`;
|
|
|
+ //const src = `${vaildMusicScoreUrl()}/instrument/#/simple-detail?id=${state.musicDetail.musicSheetId}&musicRenderType=${staffState.musicRenderType}&part-index=${staffState.partIndex}`;
|
|
|
+ const src = `https://dev.kt.colexiu.com/instrument/#/simple-detail?id=${state.musicDetail.musicSheetId}&musicRenderType=${staffState.musicRenderType}&part-index=${staffState.partIndex}`;
|
|
|
staffState.staffSrc = src
|
|
|
window.addEventListener('message', (event) => {
|
|
|
const { api, height } = event.data;
|
|
@@ -518,6 +421,7 @@ export default defineComponent({
|
|
|
state.playType = '';
|
|
|
state.params.page = 1;
|
|
|
state.list = [];
|
|
|
+ isInitAudioVisualDraw = false
|
|
|
if(state._plrl){
|
|
|
state._plrl.destroy()
|
|
|
}
|