const { createApp, ref, onMounted, nextTick, onUnmounted, computed } = Vue; const search = createApp({ setup() { // 标签数据 let tags = ref([]); let tagsFill = ref([]); // 获取容器 const containerFill = ref(null); const container = ref(null); // 计算容器尺寸 const getContainerDimensions = () => { const containerWidth = container.value.offsetWidth; const containerHeight = container.value.offsetHeight; return { containerWidth, containerHeight }; }; // 初始创建标签 const init = () => { fetch("./static/js/music.json") .then((response) => { if (!response.ok) throw new Error(`请求失败:${response.status}`); // 将响应解析为 JSON 格式 return response.json(); }) .then((data) => { // 成功获取 JSON 数据,后续处理(如使用 tags 数组) console.log("读取到的 JSON 数据:", data); // data.data.length = 1 let tagsData = data.data || []; // 提取 tags 数组 console.log("tagsData", tagsData); const { containerWidth, containerHeight } = getContainerDimensions(); const redCount = Math.min(5, tagsData.length); const redIndexes = []; while (redIndexes.length < redCount) { const randomIdx = Math.floor(Math.random() * tagsData.length); if (!redIndexes.includes(randomIdx)) redIndexes.push(randomIdx); } tagsData.forEach((item, index) => { item["type"] = getRandomOutcome(); if (redIndexes.includes(index)) item["isred"] = 1; }); tags.value = tagsData; const fillLength = tags.value.length * 1.5; let tagAll = []; for (let i = 0; i < fillLength; i++) { tagAll.push({ type: Math.floor(Math.random() * 5) + 1, }); } tagsFill.value = tagAll; nextTick(() => { tagCloud({ selector: "#bubbleContainerFill", // 元素选择器,id 或 class radius: [containerWidth / 2, containerHeight / 2], // 滚动横/纵轴半径, 默认60,单位px,取值60,[60],[60, 60] mspeed: "normal", // 滚动最大速度, 取值: slow, normal(默认), fast ispeed: "slow", // 滚动初速度, 取值: slow, normal(默认), fast direction: 45, // 初始滚动方向, 取值角度(顺时针360): 0对应top, 90对应left, 135对应right-bottom(默认)... keep: false, // 鼠标移出组件后是否继续随鼠标滚动, 取值: false, true(默认) 对应 减速至初速度滚动, 随鼠标滚动 multicolour: false, // 彩色字体,颜色随机,取值:true(默认),false }); tagCloud({ selector: "#bubbleContainer", // 元素选择器,id 或 class radius: [containerWidth / 2, containerHeight / 2], mspeed: "normal", ispeed: "normal", direction: 135, keep: false, multicolour: false, }); }); }); }; // 生成单次随机结果的函数 const getRandomOutcome = () => { const random = Math.random(); // 生成0-1之间的随机数 let cumulativeProbability = 0; const outcomes = [0.1, 0.2, 0.3, 0.4]; for (const outcome of outcomes) { cumulativeProbability += outcome; if (random < cumulativeProbability) { return outcomes.indexOf(outcome) + 1; } } }; onMounted(() => { init(); // 添加进度更新事件监听器 if (audioPlayer.value) { volume.value = audioPlayer.value.volume * 100; audioPlayer.value.addEventListener("timeupdate", getProgress); audioPlayer.value.addEventListener("loadedmetadata", getProgress); } }); // 组件卸载时清理事件监听器 onUnmounted(() => { audioPlayer?.value?.removeEventListener("timeupdate", getProgress); audioPlayer?.value?.removeEventListener("loadedmetadata", getProgress); }); const handleMouseleave = (e) => { e.target.style.animationPlayState = "running"; }; const handleMouseenter = (e) => { e.target.style.animationPlayState = "paused"; }; const audioPlayer = ref(null); const clickSongs = (songs) => { const randomIndex = Math.floor(Math.random() * songs.length); const item = songs[randomIndex]; manageAudio(item); }; // 管理音频播放 const manageAudio = (item) => { const audio = audioPlayer.value; closeAll(); setTimeout(() => { console.log("item", item); if (audio?.src != item.path) audio.src = item.path; // audio.src = "https://app.gter.net/image/miniApp/mp3/1.mp3"; audio.src = "/static/mp3/1.MP3"; audio.play().then(() => (playData.value = { ...item, state: true })); }, 500); }; // 重新播放 const rePlay = () => { if (!playData.value) return; const item = playData.value; manageAudio(item); }; // 播放 组件数据 let playData = ref(null); // 响应式数据:音量值、是否静音 let volume = ref(100); // 计算并设置音量百分比 const setVolumePercentage = (percentage) => { const volumePercent = Math.max(0, Math.min(100, percentage)); volume.value = Math.abs(~~volumePercent); // 设置音频元素的音量(范围是0-1) if (audioPlayer.value) audioPlayer.value.volume = volume.value / 100; }; // 处理音量进度条点击 const handleVolumeClick = (event) => { // 获取进度条元素 const progressBar = event.currentTarget; const rect = progressBar.getBoundingClientRect(); const clickPosition = rect.bottom - event.clientY; const percentage = (clickPosition / rect.height) * 100; setVolumePercentage(percentage); }; let volumeShow = ref(false); // 处理音量进度条拖拽 let isDragging = false; const startDrag = (event) => { isDragging = true; handleVolumeDrag(event); // 添加事件监听器 document.addEventListener("mousemove", handleVolumeDrag); document.addEventListener("mouseup", stopDrag); }; const handleVolumeDrag = (event) => { if (!isDragging) return; // 获取音量进度条元素 const progressBar = document.querySelector(".sound-control .progress"); if (!progressBar) return; const rect = progressBar.getBoundingClientRect(); // 计算拖拽位置相对于进度条的比例 let dragPosition = rect.bottom - event.clientY; // 限制在进度条范围内 dragPosition = Math.max(0, Math.min(dragPosition, rect.height)); const percentage = (dragPosition / rect.height) * 100; setVolumePercentage(percentage); }; const stopDrag = () => { isDragging = false; document.removeEventListener("mousemove", handleVolumeDrag); document.removeEventListener("mouseup", stopDrag); }; const handleVolumeShow = () => (volumeShow.value = true); const handleVolumeHide = () => (volumeShow.value = false); onUnmounted(() => { // 确保移除所有拖拽相关事件 document.removeEventListener("mousemove", handleVolumeDrag); document.removeEventListener("mouseup", stopDrag); document.removeEventListener("mousemove", handleBarDragBottomDrag); document.removeEventListener("mouseup", stopBarDragBottom); }); const progress = ref(0); // 播放进度百分比 // 响应式变量存储当前播放时间和总时长 const currentTimeFormatted = ref("00:00"); const durationFormatted = ref("00:00"); // 格式化时间函数:将秒数转换为 MM:SS 格式 const formatTime = (seconds) => { const mins = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`; }; // 更新进度的函数 const getProgress = () => { if (!audioPlayer.value) return; const currentTime = audioPlayer.value.currentTime || 0; const duration = audioPlayer.value.duration || 0; const p = duration > 0 ? (currentTime / duration) * 100 : 0; progress.value = p; // 更新时间显示 currentTimeFormatted.value = formatTime(currentTime); durationFormatted.value = formatTime(duration); }; // 快进 和 后退 10秒 const fastForward = (type = "fast") => { if (!audioPlayer.value) return; console.log("playData.value", playData.value); const src = playData.value?.path || ""; if (audioPlayer.value.src != src) { manageAudio(playData.value); return; } let currentTime = audioPlayer.value.currentTime || 0; const duration = audioPlayer.value.duration || 0; let newTime = 0; if (type == "fast") newTime = Math.min(currentTime + 10, duration); else newTime = Math.max(currentTime - 10, 0); audioPlayer.value.currentTime = newTime; getProgress(); }; // 关闭所有播放 const closeAll = () => { audioPlayer.value.pause(); playData.value && (playData.value.state = false); }; // 处理音量进度条拖拽 let isBarBottomDragging = false; const startBarDragBottom = (event) => { isBarBottomDragging = true; handleBarDragBottomDrag(event); // 添加事件监听器 document.addEventListener("mousemove", handleBarDragBottomDrag); document.addEventListener("mouseup", stopBarDragBottom); }; const stopBarDragBottom = () => { isBarBottomDragging = false; document.removeEventListener("mousemove", handleBarDragBottomDrag); document.removeEventListener("mouseup", stopBarDragBottom); }; // 直接点击进度条 跳转 const handleBarDragBottomClick = (event) => { // 获取进度条元素 const progressBar = event.currentTarget; const rect = progressBar.getBoundingClientRect(); const clickPosition = event.clientX - rect.left; const percentage = clickPosition / rect.width; // 限制百分比在0-100之间 const clampedPercentage = Math.max(0, Math.min(100, percentage)); updatePlay(clampedPercentage); }; const handleBarDragBottomDrag = (event) => { // console.log("event", event); if (!isBarBottomDragging) return; // 获取音量进度条元素 const progressBar = document.querySelector(".bottom-play .bottom-middle .progress-bar"); if (!progressBar) return; console.log("14111111111"); const rect = progressBar.getBoundingClientRect(); // 计算拖拽位置相对于进度条的比例 let dragPosition = event.clientX - rect.left; // 限制在进度条范围内 dragPosition = Math.max(0, Math.min(dragPosition, rect.width)); const percentage = dragPosition / rect.width; updatePlay(percentage); }; const updatePlay = (percentage) => { if (!audioPlayer.value) return; const duration = audioPlayer.value.duration || 0; let newTime = duration * percentage; newTime = Math.max(0, Math.min(duration, newTime)); audioPlayer.value.currentTime = newTime; getProgress(); }; return { startBarDragBottom, handleBarDragBottomClick, closeAll, fastForward, progress, durationFormatted, currentTimeFormatted, rePlay, handleVolumeHide, handleVolumeShow, stopDrag, handleVolumeDrag, startDrag, volumeShow, handleVolumeClick, setVolumePercentage, volume, audioPlayer, playData, handleMouseleave, handleMouseenter, clickSongs, tags, tagsFill, containerFill, container }; }, }).mount("#song-request-station");