原文: C# WPF 歌詞控件(支援逐字定位描色效果) 之前做了一個 模仿網易雲歌詞的控件 ,實作了加載網易雲歌詞并能随音樂播放進度定位歌詞。今天呢将在這個控件的基礎上增加逐字定位描色功能,如下圖效果(QQ音樂PC)所示:

我所使用的實作方法很簡單粗暴,把每句歌詞每個字切開,單獨顯示在一個描色的控件中,然後拼成一行完整的歌詞,随音樂播放進度去找相應的字進行描色。
而最重要的描色功能是怎麼實作的呢?
答案是:使用ClipToBounds屬性
當控件ClipToBounds屬性為TRUE時,超出控件範圍的内容将會被裁剪掉不顯示。現在你應該能明白描色功能怎麼實作了吧?
在一個自定義控件中有兩個Label,設定一個為置頂(ZINDEX最大)顯示并加上顔色,給頂部的這個Label設定ClipToBounds屬性為TRUE,然後預設頂部的Label寬度為0,描色的過程就把頂部的Label寬度慢慢增加。
最終完成的效果如下圖,為了更直覺地看到效果我給兩個Label都加上了不同的背景顔色:
當然描色時間我沒調好。當進度到達某個字時就調用那個字的控件執行一個寬度動畫,動畫目标就是置頂的Label,動畫時間就是唱這個字所花費的時間。
這裡就不把項目所有代碼貼出來了,因為都是些簡單的調用和判斷而已,隻貼描色的部分代碼。
歌詞負責描色的控件如下,每個字都單獨顯示在這個控件中
<Grid Background="Yellow">
<!--描色層-->
<Canvas Background="Black" HorizontalAlignment="Left" ClipToBounds="True" Name="ColorLayer" Panel.ZIndex="1">
<Label Name="ColorWordLabel" Foreground="Red">測</Label>
</Canvas>
<Label Name="WordLabel" >測</Label>
</Grid>
double tovalue = WordLabel.ActualWidth;
widthAnimation.From = 0;
widthAnimation.To = tovalue;
widthAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(Time));
ColorLayer.BeginAnimation(WidthProperty, widthAnimation);
背景代碼的描色其實就是播放一個動畫,動畫操作了帶有顔色的字型控件寬度,也就是ColorLayer控件,寬度從From 0開始到 To WordLabel的實際寬度,播放所需時間Duration是Time(毫秒機關),就這幾句代碼完成了描色的過程。
完整項目下載下傳:
點選下載下傳要知道普通的LRC格式歌詞是沒有記錄每個字的吟唱時間的,而QQ音樂、酷狗音樂的歌詞檔案都經過不同算法的加密保護,沒法直接讀取,是以在這個項目中我将自己建立一個歌詞格式。
那麼歌詞檔案必須要包含以下資訊:
1,完整歌詞;
2,每句歌詞的開始時間;
3,每句歌詞每個字的吟唱耗時;
為了友善讀寫将使用JSON的資料格式來儲存。
計劃:
- 制作一個簡單的描色歌詞制作工具(參考酷狗音樂的歌詞制作工具),在讀取普通的LRC歌詞後能可視化地去編輯每個字的吟唱時間,生成項目專用的歌詞檔案; [√]
- 單獨分離成一個控件; [√]
- 性能優化; [×]
------------------------------------------------------------------------------------------------------
經過不斷地縫縫補補和複制粘貼,已經完成了計劃中的1、2。(2018年4月28日
首先說第1項,歌詞制作工具,在播放音樂的同時調整描色的進度,将吟唱時間記錄到歌詞資料中,導出控件專用的NRC歌詞資料格式友善調用。制作描色的時候決定了歌詞描色的準确與否,而且還必須得比較熟悉歌曲才能制作出完美的描色歌詞,這點有待改進。
所有歌詞都調整描色完畢之後點選導出NRC檔案即可完成制作,如果在沒有将所有字描色完成之前導出會導緻歌詞顯示控件無法正常描色定位。操作方式跟酷狗的歌詞制作工具差不多,按鍵盤上鍵切到上一個字,下鍵切到下一個字。酷狗歌詞制作工具制作的描色歌詞好像會進行後期計算調整,更加準确,以後會想辦法實作。
歌詞制作工具的調用步驟是:
1,載入歌詞(可以是網易雲的或者是NRC的)
2,設定音樂的路徑
然後啟動工具點選play就可以開始制作了(最好是一遍過,反複調整的話很麻煩)
最後是我用制作工具制作的NRC歌詞播放效果示範:
歌詞顯示已經單獨分離成一個控件了,調用方法如下:
1,加載歌詞:
控件.LoadNRC(歌詞字元串);//歌詞字元串可以是網易雲的也可以是NRC的
2,在播放音樂開始時實時調用此方法更新歌詞:
控件.UpdatePositionTime(播放進度總毫秒);
3,調整音樂進度後要調用此方法重新定位歌詞:
控件.ResetPositionTime(播放進度總毫秒);
4,暫停音樂時調用此方法(同時不要再UpdatePositionTime):
控件.Pause();
控件源碼、調用示例源碼、歌詞制作工具源碼請通過Github擷取:
https://github.com/NaiveNET/NaiveRC