Эх сурвалжийг харах

优化播放器背景在切换歌曲时闪烁的问题

chendeben 11 сар өмнө
parent
commit
feef173b68

+ 119 - 12
entry/src/main/ets/view/LocalMusic.ets

@@ -154,6 +154,7 @@ export struct LocalMusic {
   @State isShowTitleBar: boolean = true //是否显示分类导航条
   @State isShowAllBar: boolean = true //是否显示播放全部条
   @State isShowSingleLineLyric: boolean = false //是否显示单行歌词
+  @State backgroundOpacity: number = 1.0 //背景透明度,用于过渡动画
   @State isShowHistory: boolean = true //是否显示最近播放
   @State isCustomizeBg: boolean = false //自定义背景界面
   @State isGridMusic: boolean = false //是否网格布局
@@ -457,7 +458,11 @@ export struct LocalMusic {
           this.cover = this.currentSong.pixelMapPath;
           
           // 更新背景
-          this.updateMusicBackground();
+          if (this.isMusicBGCover && this.cover && StrUtil.isNotEmpty(this.cover)) {
+            this.setImageColor2(this.cover);
+          } else {
+            this.getFixedDefaultBackground();
+          }
         }
 
         LogUtils.getInstance().LOGI(`Heanup LocalMusic: Restored playlist from UnifiedPlayerService - ${this.songList.length} songs, index ${this.curIndex}, current song: ${this.currentSong?.name || 'null'}`);
@@ -1135,7 +1140,11 @@ export struct LocalMusic {
           AppStorage.setOrCreate('currentSong',this.currentSong);
           
           // 更新背景
-          this.updateMusicBackground();
+          if (this.isMusicBGCover && this.cover && StrUtil.isNotEmpty(this.cover)) {
+            this.setImageColor2(this.cover);
+          } else {
+            this.getFixedDefaultBackground();
+          }
         }
 
         LogUtils.getInstance().LOGI(`Heanup LocalMusic: mkDownLoadDir - UI updated with existing playlist: ${this.songList.length} songs, current index: ${this.curIndex}, current song: ${this.currentSong?.name || 'none'}`);
@@ -7227,6 +7236,7 @@ export struct LocalMusic {
     // .transition(TransitionEffect.asymmetric(TransitionEffect.scale({ x: 1.2, y: 1.2 }).animation({ duration: 500 }),
     //   TransitionEffect.scale({ x: 0, y: 0 })  ))
     .backgroundBrightness({ rate: this.isPuraWP() ? 0.1 : 0, lightUpDegree: -0.1 })
+    .opacity(this.backgroundOpacity)
     .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
     .onClick(() => {
       // this.startAutoHide()
@@ -12521,28 +12531,125 @@ export struct LocalMusic {
           // 注意:不再手动调用 startPlayOrResumePlay(),因为 UnifiedPlayerService 已经处理了播放逻辑
         });
         
-        // 更新背景
-        this.updateMusicBackground();
+        // 平滑更新背景
+        this.updateMusicBackgroundWithAnimation();
       }, 500);
     }else{
       this.cover = this.songList[this.curIndex].pixelMapPath
       // 注意:不再手动调用 startPlayOrResumePlay(),因为 UnifiedPlayerService 已经处理了播放逻辑
       
-      // 更新背景
-      this.updateMusicBackground();
+      // 平滑更新背景
+      this.updateMusicBackgroundWithAnimation();
     }
 
   }
 
   /**
-   * 更新音乐播放背景
+   * 平滑更新音乐播放背景 - 带淡入淡出动画
    */
-  private updateMusicBackground() {
-    if (this.isMusicBGCover && this.cover !== undefined && StrUtil.isNotEmpty(this.cover)) {
-      this.setImageColor2(this.cover);
-    } else {
-      this.getImageColor();
+  private updateMusicBackgroundWithAnimation() {
+    if (!this.isMusicBGCover || !this.cover || StrUtil.isEmpty(this.cover)) {
+      this.getFixedDefaultBackgroundWithAnimation();
+      return;
+    }
+
+    // 第一步:淡出当前背景
+    this.getUIContext()?.animateTo({
+      duration: 300,
+      curve: Curve.EaseOut
+    }, () => {
+      this.backgroundOpacity = 0.3;
+    });
+
+    // 第二步:延迟后更新背景并淡入
+    setTimeout(() => {
+      this.setImageColor2(this.cover!);
+      
+      // 第三步:淡入新背景
+      setTimeout(() => {
+        this.getUIContext()?.animateTo({
+          duration: 400,
+          curve: Curve.EaseIn
+        }, () => {
+          this.backgroundOpacity = 1.0;
+        });
+      }, 100);
+    }, 350);
+  }
+
+  /**
+   * 获取固定的默认背景 - 根据当前歌曲索引生成固定背景,避免闪烁
+   */
+  private getFixedDefaultBackground() {
+    if (!this.context) {
+      return;
+    }
+    
+    // 使用当前歌曲索引生成固定的背景,而不是随机
+    let bg = Utility.getMusisBg2(this.curIndex);
+    this.imageLabel = bg;
+
+    ColorConversion.setSysBarLightBackground(true);
+    this.context.resourceManager.getMediaContent(bg)
+      .then((value: Uint8Array) => {
+        let buffer = value.buffer as ArrayBuffer;
+        image.createImageSource(buffer).createPixelMap().then((pixelMap) => {
+          effectKit.createColorPicker(pixelMap, (error, colorPicker) => {
+            if (error) {
+              Logger.error('Failed to create color picker.');
+            } else {
+              let color = colorPicker.getLargestProportionColor();
+              let colorArr = ColorConversion.dealColor(color.red, color.green, color.blue);
+              this.imageColor = `rgba(${colorArr[0]}, ${colorArr[1]}, ${colorArr[2]}, 1)`;
+            }
+          })
+          let headFilter = effectKit.createEffect(pixelMap);
+          if (headFilter !== null) {
+            headFilter.blur(15);
+            headFilter.getEffectPixelMap().then((value) => {
+              this.imageLabelBg = value;
+            })
+          }
+        })
+          .catch((error: BusinessError) => {
+            Logger.error(`${error.code} + ${error.message}`)
+          })
+      })
+      .catch((error: BusinessError) => {
+        Logger.error(`Failed to load background: ${error.code} + ${error.message}`)
+      })
+  }
+
+  /**
+   * 带动画的固定默认背景更新
+   */
+  private getFixedDefaultBackgroundWithAnimation() {
+    if (!this.context) {
+      return;
     }
+
+    // 第一步:淡出当前背景
+    this.getUIContext()?.animateTo({
+      duration: 300,
+      curve: Curve.EaseOut
+    }, () => {
+      this.backgroundOpacity = 0.3;
+    });
+
+    // 第二步:延迟后更新背景并淡入
+    setTimeout(() => {
+      this.getFixedDefaultBackground();
+      
+      // 第三步:淡入新背景
+      setTimeout(() => {
+        this.getUIContext()?.animateTo({
+          duration: 400,
+          curve: Curve.EaseIn
+        }, () => {
+          this.backgroundOpacity = 1.0;
+        });
+      }, 100);
+    }, 350);
   }
 
   // 存储已播放的歌曲索引