| 
					
				 | 
			
			
				@@ -1,361 +1,359 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 <template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	<view class="danmaku-container" :style="{ height: height + 'px' }"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		<view class="danmaku-stage"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			<view  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				v-for="item in visibleDanmakus"  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				:key="item.id" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				class="danmaku-item" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				:class="[`danmaku-track`, { 'danmaku-scrolling': item.isScrolling }]" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				:style="getDanmakuStyle(item)" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				<view class="danmaku-content"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					<image class="danmaku-avatar" :src="item.icon || defaultAvatar" mode="aspectFill"></image> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					<view class="danmaku-text">{{ item.msg }}</view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				</view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			</view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		</view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	</view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <view class="danmaku-container" :style="{ height: height + 'px' }"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <view class="danmaku-stage"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            <view 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                v-for="item in visibleDanmakus" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                :key="item.id" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                class="danmaku-item" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                :class="[`danmaku-track`, { 'danmaku-scrolling': item.isScrolling }]" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                :style="getDanmakuStyle(item)" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            > 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                <view class="danmaku-content"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    <image class="danmaku-avatar" :src="item.icon || defaultAvatar" mode="aspectFill"></image> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    <view class="danmaku-text">{{ item.msg }}</view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                </view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            </view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        </view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    </view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 <script setup> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { ref, computed, onMounted, onUnmounted, watch } from 'vue' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { ref, computed, onMounted, onUnmounted, watch, nextTick } from "vue"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const props = defineProps({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	danmakuList: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		type: Array, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		default: () => [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	height: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		type: Number, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		default: 200 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	infinite: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		type: Boolean, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		default: true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	speed: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		type: Number, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		default: 100 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	trackCount: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		type: Number, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		default: 8 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	spacing: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		type: Number, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		default: 20 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const emit = defineEmits(['danmakuComplete']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const visibleDanmakus = ref([]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const animationTimer = ref(null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const danmakuIdCounter = ref(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const trackOccupancy = ref(new Array(props.trackCount).fill(0)) // 记录每个轨道的占用情况 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    danmakuList: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        type: Array, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        default: () => [], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    height: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        type: Number, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        default: 200, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    infinite: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        type: Boolean, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        default: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    speed: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        type: Number, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        default: 100, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    trackCount: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        type: Number, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        default: 8, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    spacing: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        type: Number, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        default: 20, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const emit = defineEmits(["danmakuComplete"]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const visibleDanmakus = ref([]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const animationTimer = ref(null); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const danmakuIdCounter = ref(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const trackOccupancy = ref(new Array(props.trackCount).fill(0)); // 记录每个轨道的占用情况 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 监听trackCount变化,重新初始化trackOccupancy 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-watch(() => props.trackCount, (newCount) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	trackOccupancy.value = new Array(newCount).fill(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+watch( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    () => props.trackCount, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (newCount) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        trackOccupancy.value = new Array(newCount).fill(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const trackHeight = computed(() => props.height / props.trackCount) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const trackHeight = computed(() => props.height / props.trackCount); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 默认头像 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const defaultAvatar = 'https://birdseye-img.sysuimars.com/youwei-uniapp/img/default-avatar.png' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const defaultAvatar = "https://birdseye-img.sysuimars.com/youwei-uniapp/img/default-avatar.png"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const getDanmakuStyle = (danmaku) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 获取屏幕宽度,兼容不同平台 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const screenWidth = uni.getSystemInfoSync().screenWidth || 375 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 增加更多的额外距离确保弹幕完全离开可视范围 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const extraDistance = 200 // 增加缓冲距离 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const duration = (screenWidth + danmaku.width + extraDistance) / props.speed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const trackSpacing = calculateTrackSpacing() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const danmakuHeight = calculateDanmakuHeight() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 计算弹幕的垂直位置,确保在轨道中居中且不超出容器边界 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const trackTop = danmaku.track * trackSpacing 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const centerOffset = trackSpacing / 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const topPosition = Math.max( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		danmakuHeight / 2, // 确保不超出顶部 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		Math.min( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			trackTop + centerOffset, // 轨道中心位置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			props.height - danmakuHeight / 2 // 确保不超出底部 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		top: `${topPosition}px`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		left: `${danmaku.left}px`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		transition: `left ${duration}s linear` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 获取屏幕宽度,兼容不同平台 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const screenWidth = uni.getSystemInfoSync().screenWidth || 375; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 计算动画总距离和时间,与 addDanmaku 保持一致 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const totalDistance = screenWidth + danmaku.width + 300; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const duration = totalDistance / props.speed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const trackSpacing = calculateTrackSpacing(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const danmakuHeight = calculateDanmakuHeight(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 计算弹幕的垂直位置,确保在轨道中居中且不超出容器边界 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const trackTop = danmaku.track * trackSpacing; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const centerOffset = trackSpacing / 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const topPosition = Math.max( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        danmakuHeight / 2, // 确保不超出顶部 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Math.min( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            trackTop + centerOffset, // 轨道中心位置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            props.height - danmakuHeight / 2 // 确保不超出底部 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        top: `${topPosition}px`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        left: `${danmaku.left}px`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        transition: danmaku.isScrolling ? `left ${duration}s linear` : "none", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 计算弹幕实际宽度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const calculateDanmakuWidth = (text) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 更精确的宽度计算:每个字符约16px,头像32px,内边距40px,额外缓冲20px 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return text.length * 16 + 32 + 40 + 20 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 更精确的宽度计算:每个字符约16px,头像32px,内边距40px,额外缓冲20px 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return text.length * 16 + 32 + 40 + 20; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 计算弹幕实际高度 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const calculateDanmakuHeight = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return 48 // 弹幕高度约48rpx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return 48; // 弹幕高度约48rpx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 计算轨道间距 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const calculateTrackSpacing = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const danmakuHeight = calculateDanmakuHeight() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const trackHeight = props.height / props.trackCount 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 增加轨道间距,避免弹幕重叠 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const minSpacing = danmakuHeight + 30 // 增加间距到30px 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return Math.max(minSpacing, trackHeight) // 确保轨道间距足够 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const danmakuHeight = calculateDanmakuHeight(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const trackHeight = props.height / props.trackCount; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 增加轨道间距,避免弹幕重叠 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const minSpacing = danmakuHeight + 30; // 增加间距到30px 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return Math.max(minSpacing, trackHeight); // 确保轨道间距足够 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 查找可用轨道 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const findAvailableTrack = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const currentTime = Date.now() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 清理过期的轨道占用记录 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	for (let i = 0; i < trackOccupancy.value.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (trackOccupancy.value[i] < currentTime) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			trackOccupancy.value[i] = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 简化轨道分配:使用较少的轨道数量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const finalTracks = Math.min(3, props.trackCount) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 直接寻找空闲轨道 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	for (let i = 0; i < finalTracks; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (trackOccupancy.value[i] === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			return i 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 如果所有轨道都被占用,选择第一个轨道 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 只使用一条轨道 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const createDanmaku = (text, avatar = null) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const id = ++danmakuIdCounter.value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const track = findAvailableTrack() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const width = calculateDanmakuWidth(text) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 获取屏幕宽度,兼容不同平台 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const screenWidth = uni.getSystemInfoSync().screenWidth || 375 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const left = screenWidth + props.spacing 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 简化轨道占用时间计算 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const duration = (screenWidth + width + 200) / props.speed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const endTime = Date.now() + duration * 1000 // 移除额外缓冲时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	trackOccupancy.value[track] = endTime 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		msg: text, // 修改为msg字段,与模板保持一致 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		icon: avatar, // 修改为icon字段,与模板保持一致 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		track, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		width, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		left, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		isScrolling: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		startTime: Date.now() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const id = ++danmakuIdCounter.value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const track = findAvailableTrack(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const width = calculateDanmakuWidth(text); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 获取屏幕宽度,兼容不同平台 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const screenWidth = uni.getSystemInfoSync().screenWidth || 375; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const left = screenWidth + props.spacing; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 计算弹幕完全离开屏幕的时间,增加缓冲距离 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const totalDistance = screenWidth + width + 300; // 屏幕宽度 + 弹幕宽度 + 缓冲距离 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const duration = totalDistance / props.speed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const endTime = Date.now() + duration * 1000; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    trackOccupancy.value[track] = endTime; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        msg: text, // 修改为msg字段,与模板保持一致 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        icon: avatar, // 修改为icon字段,与模板保持一致 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        track, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        width, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        left, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        isScrolling: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        startTime: Date.now(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const addDanmaku = (msg, icon = null) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	console.log('添加弹幕:', { msg, icon }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const danmaku = createDanmaku(msg, icon)	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	console.log('创建的弹幕对象:', danmaku) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	visibleDanmakus.value.push(danmaku) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	console.log('当前可见弹幕数量:', visibleDanmakus.value.length) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	setTimeout(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		danmaku.isScrolling = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		// 确保弹幕完全离开可视范围才消失,增加更多缓冲距离 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		danmaku.left = -(danmaku.width + 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	}, 50) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 获取屏幕宽度,兼容不同平台 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const screenWidth = uni.getSystemInfoSync().screenWidth || 375 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 增加更多的额外距离确保弹幕完全离开可视范围 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const extraDistance = 200 // 增加缓冲距离 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const duration = (screenWidth + danmaku.width + extraDistance) / props.speed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	setTimeout(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		removeDanmaku(danmaku.id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	}, duration * 1000) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const danmaku = createDanmaku(msg, icon); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    visibleDanmakus.value.push(danmaku); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 获取屏幕宽度,兼容不同平台 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const screenWidth = uni.getSystemInfoSync().screenWidth || 375; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 计算动画总距离和时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const totalDistance = screenWidth + danmaku.width + 500; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const duration = totalDistance / props.speed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 检查是否是第一条弹幕(通过检查当前可见弹幕数量) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const isFirstDanmaku = visibleDanmakus.value.length === 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 给第一条弹幕更多准备时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const startDelay = isFirstDanmaku ? 500 : 100; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    setTimeout(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        danmaku.isScrolling = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 确保弹幕完全离开可视范围才消失 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        danmaku.left = -(danmaku.width + 500); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 在动画完成后移除弹幕,第一条弹幕给更多缓冲时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const removeDelay = isFirstDanmaku ? duration * 1000 + 1000 : duration * 1000; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        setTimeout(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            removeDanmaku(danmaku.id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }, removeDelay); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, startDelay); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const removeDanmaku = (id) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const index = visibleDanmakus.value.findIndex(item => item.id === id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (index > -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		visibleDanmakus.value.splice(index, 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		emit('danmakuComplete', id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const index = visibleDanmakus.value.findIndex((item) => item.id === id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (index > -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        visibleDanmakus.value.splice(index, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        emit("danmakuComplete", id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const clearDanmakus = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	visibleDanmakus.value = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 清空轨道占用记录 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	trackOccupancy.value = new Array(props.trackCount).fill(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    visibleDanmakus.value = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 清空轨道占用记录 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    trackOccupancy.value = new Array(props.trackCount).fill(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const startDanmakuAnimation = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	console.log('开始弹幕动画,数据列表:', props.danmakuList) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (props.danmakuList.length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		console.log('弹幕列表为空,不启动动画') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	let currentIndex = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const playNext = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (currentIndex >= props.danmakuList.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			if (props.infinite) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				currentIndex = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		const danmaku = props.danmakuList[currentIndex] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		console.log('播放弹幕:', danmaku) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		// 直接播放弹幕,不检查轨道占用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		addDanmaku(danmaku.msg, danmaku.icon) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		currentIndex++ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		// 减少弹幕播放间隔 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		const baseInterval = Math.max(2000, props.height * 2) // 减少基础间隔 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		const minInterval = baseInterval 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		const maxInterval = baseInterval + 2000 // 减少随机间隔范围 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		const interval = Math.random() * (maxInterval - minInterval) + minInterval 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		animationTimer.value = setTimeout(playNext, interval) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	playNext() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (props.danmakuList.length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let currentIndex = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const playNext = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (currentIndex >= props.danmakuList.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (props.infinite) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                currentIndex = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const danmaku = props.danmakuList[currentIndex]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 直接播放弹幕 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        addDanmaku(danmaku.msg, danmaku.icon); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        currentIndex++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 使用固定的较长间隔时间,确保弹幕之间有足够距离 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const screenWidth = uni.getSystemInfoSync().screenWidth || 375; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const danmakuWidth = calculateDanmakuWidth(danmaku.msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const totalDistance = screenWidth + danmakuWidth + 300; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const totalTime = totalDistance / props.speed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 使用总时间的80%作为间隔,确保弹幕之间有足够距离 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const intervalTime = totalTime * 0.8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 固定间隔播放下一条弹幕 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        animationTimer.value = setTimeout(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            playNext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }, intervalTime * 1000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 给第一条弹幕更多准备时间,确保组件完全初始化 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    setTimeout(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        playNext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 800); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const stopDanmakuAnimation = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (animationTimer.value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		clearTimeout(animationTimer.value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		animationTimer.value = null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (animationTimer.value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        clearTimeout(animationTimer.value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        animationTimer.value = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-watch(() => props.danmakuList, (newList) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	console.log('弹幕数据变化:', newList) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (newList.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		console.log('弹幕数据不为空,重新启动动画') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		stopDanmakuAnimation() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		clearDanmakus() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		startDanmakuAnimation() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		console.log('弹幕数据为空') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}, { deep: true }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+watch( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    () => props.danmakuList, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (newList) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (newList.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            stopDanmakuAnimation(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            clearDanmakus(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 移除自动启动动画,改为手动调用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // startDanmakuAnimation() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { deep: true } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 onMounted(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (props.danmakuList.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		startDanmakuAnimation() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (props.danmakuList.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        startDanmakuAnimation(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 onUnmounted(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	stopDanmakuAnimation() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    stopDanmakuAnimation(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 defineExpose({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	addDanmaku, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	clearDanmakus, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	startDanmakuAnimation, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	stopDanmakuAnimation 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    addDanmaku, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    clearDanmakus, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    startDanmakuAnimation, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    stopDanmakuAnimation, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 </script> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 <style lang="scss" scoped> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 .danmaku-container { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	width: 100%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	position: relative; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	overflow: hidden; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// background: rgba(0, 0, 0, 0.1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	border-radius: 8rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    width: 100%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    position: relative; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    overflow: hidden; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // background: rgba(0, 0, 0, 0.1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    border-radius: 8rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 .danmaku-stage { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	width: 100%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	height: 100%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	position: relative; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    width: 100%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    height: 100%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    position: relative; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 .danmaku-item { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	position: absolute; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	top: 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	left: 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	z-index: 10; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	pointer-events: none; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	&.danmaku-scrolling { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		transition: left linear; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 确保弹幕在轨道中居中显示 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	transform: translateY(-50%); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    position: absolute; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    top: 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    left: 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    z-index: 10; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pointer-events: none; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    &.danmaku-scrolling { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        transition: left linear; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 确保弹幕在轨道中居中显示 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    transform: translateY(-50%); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 .danmaku-content { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	align-items: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	background: rgba(0, 0, 0, 0.6); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	border-radius: 20rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	padding: 8rpx 20rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	backdrop-filter: blur(10rpx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	border: 1rpx solid rgba(255, 255, 255, 0.2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.3); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	width: fit-content; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	min-width: 120rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 确保弹幕内容不会超出容器边界 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	max-height: 48rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	overflow: hidden; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 防止弹幕在滚动过程中高度变化 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	line-height: 1.2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 增加内边距确保文字有足够空间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	box-sizing: border-box; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    align-items: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    background: rgba(0, 0, 0, 0.6); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    border-radius: 20rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    padding: 8rpx 20rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    backdrop-filter: blur(10rpx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    border: 1rpx solid rgba(255, 255, 255, 0.2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.3); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    width: fit-content; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    min-width: 120rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 确保弹幕内容不会超出容器边界 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    max-height: 48rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    overflow: hidden; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 防止弹幕在滚动过程中高度变化 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    line-height: 1.2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 增加内边距确保文字有足够空间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    box-sizing: border-box; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 .danmaku-avatar { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	width: 32rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	height: 32rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	border-radius: 50%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	margin-right: 12rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	border: 2rpx solid rgba(255, 255, 255, 0.3); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	flex-shrink: 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 确保头像高度稳定 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	object-fit: cover; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    width: 32rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    height: 32rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    border-radius: 50%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    margin-right: 12rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    border: 2rpx solid rgba(255, 255, 255, 0.3); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    flex-shrink: 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 确保头像高度稳定 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    object-fit: cover; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 .danmaku-text { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	color: #000; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	font-size: 24rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	font-weight: 500; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.5); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	white-space: nowrap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	overflow: hidden; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	text-overflow: ellipsis; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	max-width: 400rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	flex: 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 确保文字高度稳定 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	line-height: 1.2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	height: 32rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	align-items: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// 增加文字间距确保显示完整 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	letter-spacing: 1rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    color: #000; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    font-size: 24rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    font-weight: 500; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.5); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    white-space: nowrap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    overflow: hidden; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    text-overflow: ellipsis; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    max-width: 400rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    flex: 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 确保文字高度稳定 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    line-height: 1.2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    height: 32rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    display: flex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    align-items: center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 增加文字间距确保显示完整 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    letter-spacing: 1rpx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 .danmaku-track .danmaku-content { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	background: rgba(244, 246, 248, 0.6); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    background: rgba(244, 246, 248, 0.6); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 </style> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 |