Explorar o código

优化歌词的卡拉ok效果

onecold hai 7 meses
pai
achega
b0bf8a7ef1

+ 1 - 33
entry/src/main/ets/view/LocalMusic.ets

@@ -9786,7 +9786,7 @@ export struct LocalMusic {
       .setTextSize(15)
       .setCacheSize(4)
       .setTextColor("#FFFFFF")
-      .setHighlightColor("#FFFFFF")
+      .setHighlightColor(this.currentHighLightLyricColor)
       .setHighlightScale(1.2)
       .setEmptyHint("")
       .setAlignMode('center')
@@ -11838,38 +11838,6 @@ export struct LocalMusic {
       })
 
 
-      if (!isPip) {
-        Row() {
-          Text(`歌词模糊:`)
-            .fontSize(14)
-            .fontColor(Color.White)
-          Slider({
-            value: isPip ? this.blurDegreePip : this.blurDegree,
-            min: 0,
-            max: 5,
-            step: 0.1,
-            style: SliderStyle.OutSet
-          })
-            .blockColor(this.themeColor)
-            .trackColor($r('app.color.speed_text_color'))
-            .selectedColor(Color.White)
-            .trackThickness(6)
-            .onChange((value: number) => {
-              this.setBlurDegree(value, isPip)
-
-            })
-            .width('76%')
-
-
-        }
-        .margin({
-          left: 20,
-          right: 15,
-          top: 5,
-          bottom: 15
-        })
-      }
-
       Row() {
         this.pushLyricButton($r('app.media.cut_current'), 0, '本地歌词')
         this.pushLyricButton($r('app.media.white_search'), 1, '获取歌词')

+ 30 - 8
lib/src/main/ets/bean/LyricLine.ts

@@ -27,7 +27,7 @@ export class LyricLine {
      * 1. words 数组不为空
      * 2. 每个 word 对象都有有效的开始时间(>= 0)
      * 3. 每个 word 对象都有有效的时长(> 0)
-     * 4. 至少有一个 word 包含非空文本
+     * 4. 每个 word只能包含一个中文字或者一个英文单词
      * @returns true 表示是逐字歌词格式,false 表示是普通歌词格式
      */
     hasWords(): boolean {
@@ -36,17 +36,39 @@ export class LyricLine {
             return false;
         }
 
-        // 检查是否有至少一个有效的 word 对象
-        let hasValidWord = false;
+        // 检查是否所有 word 对象都符合逐字歌词的条件
         for (let i = 0; i < this.words.length; i++) {
             const word = this.words[i];
-            // word 必须有:有效的开始时间、有效的时长、非空文本
-            if (word && word.startTime >= 0 && word.duration > 0 && word.word && word.word.length > 0) {
-                hasValidWord = true;
-                break;
+
+            // word 必须存在
+            if (!word || !word.word) {
+                return false;
+            }
+            if(word.word.length==1){
+                return true
+            }
+            // 必须有有效的时间信息
+            if (word.startTime < 0 || word.duration <= 0) {
+                return false;
+            }
+
+
+            // 检查 word 是否只包含一个中文字或一个英文单词
+            const wordText = word.word.trim();
+
+            // 判断是否是单个中文字符
+            const isSingleChineseChar = /^[\u4e00-\u9fa5]$/.test(wordText);
+
+            // 判断是否是单个英文单词(不含空格)
+            const isSingleEnglishWord = /^[a-zA-Z]+$/.test(wordText) && !wordText.includes(' ');
+
+            // 如果既不是单个中文字,也不是单个英文单词,则不是逐字歌词
+            if (!isSingleChineseChar && !isSingleEnglishWord) {
+                return false;
             }
         }
 
-        return hasValidWord;
+        // 所有 word 都符合条件,是逐字歌词
+        return true;
     }
 }

+ 15 - 90
lib/src/main/ets/view/LyricView2.ets

@@ -232,7 +232,6 @@ export struct LyricView2 {
         .width('100%')
         .height('100%')
         .layoutWeight(1)
-        .chainAnimation(true)
         .scrollBar(BarState.Off)
         .fadingEdge(true,{fadingEdgeLength:LengthMetrics.percent(20)})
         .edgeEffect(EdgeEffect.Spring)
@@ -322,6 +321,14 @@ export struct LyricView2 {
                             index == this.currentIndex ? this.textHighlightColor : this.textColor : this.textColor)
                         .fontWeight(index == this.currentIndex && this.isHighlightBold ? FontWeight.Bold : this.textWeight)
                         .margin({ top: 4 })
+                        .animation({
+                            duration: 150,
+                            curve: Curve.Linear
+                        })
+                        .blendMode(
+                            index == this.currentIndex ? BlendMode.DST_IN : undefined,
+                            index == this.currentIndex ? BlendApplyType.OFFSCREEN : undefined
+                        )
                 }
                 .justifyContent(this.alignMode === 'center' ? FlexAlign.Center : FlexAlign.Start)
                 .width(this.alignMode == 'center' ? '100%' :index == this.currentIndex ?'95%': '85%')
@@ -346,9 +353,9 @@ export struct LyricView2 {
      */
     getLyricItemLinearGradient(item: LyricLine, index: number): [ResourceColor, number][] {
         // 只对当前播放行且包含逐字数据的行应用卡拉OK效果
-        if (index !== this.currentIndex || !item.hasWords() || item.words.length === 0) {
+        if (index !== this.currentIndex  || item.words.length === 0) {
             //console.info('heanup', `getLyricItemLinearGradient - 非高亮行或无逐字数据: index=${index}, currentIndex=${this.currentIndex}, hasWords=${item.hasWords()}, wordsCount=${item.words.length}`)
-            return [[Color.Transparent, 0.0], [Color.Transparent, 1.0]]
+            return [[Color.White, 0.0], [Color.White, 1.0]]
         }
 
         // 计算该行歌词的总时长
@@ -374,13 +381,11 @@ export struct LyricView2 {
 
         value = Math.max(0, Math.min(1, value))
 
-        //console.info('heanup', `getLyricItemLinearGradient - diff=${diff}, value=${value}, textHighlightColor=${this.textHighlightColor}, textColor=${this.textColor}`)
 
         return [[this.textHighlightColor, 0.0],
             [this.textHighlightColor, value],
             [this.textColor, value],
             [this.textColor, 1.0]]
-
     }
 
     /**
@@ -394,8 +399,8 @@ export struct LyricView2 {
     getWordByWordLyricLyricItemLinearGradient(item: LyricLine, word: LyricWord, index: number): [ResourceColor, number][] {
         // 非高亮行或无效数据,返回透明
         if (index !== this.currentIndex || !word || !word.word) {
-            console.info('heanup', `getWordByWordLyricLyricItemLinearGradient - 非高亮行或无效word: index=${index}, currentIndex=${this.currentIndex}`)
-            return [[Color.Transparent, 0.0], [Color.Transparent, 1.0]]
+            //console.info('heanup', `getWordByWordLyricLyricItemLinearGradient - 非高亮行或无效word: index=${index}, currentIndex=${this.currentIndex}`)
+            return [[Color.White, 0.0], [Color.White, 1.0]]
         }
 
         // 计算该字的播放进度
@@ -404,7 +409,7 @@ export struct LyricView2 {
 
         // 异常情况处理
         if (wordDuration <= 0) {
-            console.info('heanup', `getWordByWordLyricLyricItemLinearGradient - word时长<=0: startTime=${word.startTime}, duration=${word.duration}`)
+            //console.info('heanup', `getWordByWordLyricLyricItemLinearGradient - word时长<=0: startTime=${word.startTime}, duration=${word.duration}`)
             // 如果时长无效,检查当前播放位置是否已到达开始时间
             if (this.currentMediaPosition >= word.startTime) {
                 // 已开始播放,全部高亮
@@ -452,8 +457,7 @@ export struct LyricView2 {
                         .fontSize(index == this.currentIndex ?this.textSize*this.controller.getHighlightScale():this.textSize)
                         .fontColor(this.currentMediaPosition >= word.startTime ?
                             index == this.currentIndex ? this.textHighlightColor : this.textColor : this.textColor)
-                        .fontWeight(this.currentMediaPosition >= word.startTime && this.isHighlightBold ?
-                            index == this.currentIndex? FontWeight.Bold : this.textWeight: this.textWeight)
+                        .fontWeight(index == this.currentIndex? FontWeight.Bold : this.textWeight)
                         .margin(isEnglish(word.word) ?{ right:4 }:{})
                         .visibility(this.isSingleLine?
                             (index == this.currentIndex ?Visibility.Visible:Visibility.None)
@@ -482,7 +486,7 @@ export struct LyricView2 {
                         .fontSize(index == this.currentIndex ?this.textSize*this.controller.getHighlightScale():this.textSize)
                         .fontColor(this.currentMediaPosition >= item.beginTime ?
                             index == this.currentIndex ? this.textHighlightColor : this.textColor : this.textColor)
-                        .fontWeight(index == this.currentIndex && this.isHighlightBold ? FontWeight.Bold : this.textWeight)
+                        .fontWeight(index == this.currentIndex? FontWeight.Bold : this.textWeight)
                         .margin({ top: 4 })
                 }
                 .justifyContent(this.alignMode === 'center' ? FlexAlign.Center : FlexAlign.Start)
@@ -494,85 +498,6 @@ export struct LyricView2 {
     }
 
 
-    // @Builder
-    // Normalyric(item: LyricLine, index: number) {
-    //     Column() {
-    //         // 完全复制 LyricList 的实现结构
-    //         Row({ space: 10 }) {
-    //             Text(item.text)
-    //                 .maxLines(index == this.currentIndex ? 1 : 2)
-    //                 .textOverflow({ overflow: TextOverflow.Ellipsis })
-    //                 .padding(5)
-    //                 .textAlign(this.alignMode == 'center' ? TextAlign.Center : TextAlign.Start)
-    //                 .fontWeight(index == this.currentIndex && this.isHighlightBold ? FontWeight.Bold : this.textWeight)
-    //                 .width('100%')
-    //                 .fontColor(index == this.currentIndex ? this.textHighlightColor : this.textColor)
-    //                 .fontSize(index == this.currentIndex ? this.textSize * this.controller.getHighlightScale() : this.textSize)
-    //                 .blendMode(
-    //                     index == this.currentIndex ? BlendMode.DST_IN : undefined,
-    //                     index == this.currentIndex ? BlendApplyType.OFFSCREEN : undefined
-    //                 )
-    //                 // 关键:添加线性动画,使渐变平滑过渡
-    //                 .animation({
-    //                     duration: 500,
-    //                     curve: Curve.Linear
-    //                 })
-    //         }
-    //         // 在 Row 上应用渐变
-    //         .linearGradient(index == this.currentIndex ? {
-    //             direction: GradientDirection.Right,
-    //             colors: this.getLyricItemLinearGradient(item, index)
-    //         } : undefined)
-    //         .blendMode(
-    //             index == this.currentIndex ? BlendMode.SRC_OVER : undefined,
-    //             index == this.currentIndex ? BlendApplyType.OFFSCREEN : undefined
-    //         )
-    //         .borderRadius(5)
-    //         .justifyContent(this.alignMode === 'center' ? FlexAlign.Center : FlexAlign.Start)
-    //         .width(this.alignMode == 'center' ? '100%' : (index == this.currentIndex ? '95%' : '85%'))
-    //         .visibility(this.isSingleLine ?
-    //             (index == this.currentIndex ? Visibility.Visible : Visibility.None)
-    //             : Visibility.Visible)
-    //
-    //         // 中文翻译(整行显示)
-    //         if (item.translation) {
-    //             Row({ space: 0 }) {
-    //                 Text(item.translation)
-    //                     .fontSize(index == this.currentIndex ? this.textSize * this.controller.getHighlightScale() : this.textSize)
-    //                     .fontColor(this.currentMediaPosition >= item.beginTime ?
-    //                         index == this.currentIndex ? this.textHighlightColor : this.textColor : this.textColor)
-    //                     .fontWeight(index == this.currentIndex && this.isHighlightBold ? FontWeight.Bold : this.textWeight)
-    //                     .margin({ top: 4 })
-    //                     .blendMode(
-    //                         index == this.currentIndex ? BlendMode.DST_IN : undefined,
-    //                         index == this.currentIndex ? BlendApplyType.OFFSCREEN : undefined
-    //                     )
-    //                     // 关键:添加线性动画,使渐变平滑过渡
-    //                     .animation({
-    //                         duration: 150,
-    //                         curve: Curve.Linear
-    //                     })
-    //             }
-    //             .justifyContent(this.alignMode === 'center' ? FlexAlign.Center : FlexAlign.Start)
-    //             .width(this.alignMode == 'center' ? '100%' : (index == this.currentIndex ? '95%' : '85%'))
-    //             // 在 Row 上应用渐变
-    //             .linearGradient(index == this.currentIndex ? {
-    //                 direction: GradientDirection.Right,
-    //                 colors: this.getLyricItemLinearGradient(item, index)
-    //             } : undefined)
-    //             .blendMode(
-    //                 index == this.currentIndex ? BlendMode.SRC_OVER : undefined,
-    //                 index == this.currentIndex ? BlendApplyType.OFFSCREEN : undefined
-    //             )
-    //         }
-    //     }
-    // }
-
-
-
-    isTopBottomLine(index:number){
-        return  index === 0 || index === this.listAdapter.totalCount()  - 1;
-    }
     //修复get Property index out of bounds
     private handleSeekAction() {
         clearTimeout(this.seekUiHideTimeout);