基于WPF實(shí)現(xiàn)彈幕效果的示例代碼
WPF 實(shí)現(xiàn)彈幕效果
框架使用大于等于.NET40
;
Visual Studio 2022
;
項(xiàng)目使用 MIT 開源許可協(xié)議;
此篇代碼目的只是為了分享思路
實(shí)現(xiàn)基礎(chǔ)彈幕一定是要使用Canvas
比較簡單,只需實(shí)現(xiàn)Left
動(dòng)畫從右到左。
- 彈幕消息使用
Border
做彈幕背景。 - 內(nèi)容使用
TextBlock
做消息文本展示。 - 當(dāng)動(dòng)畫執(zhí)行完成默認(rèn)移除
Canvas
中的彈幕控件。 - 使用這種方式去加載彈幕
GPU
會(huì)占較高。
1) 準(zhǔn)備BarrageExample.xaml如下:
<UserControl?x:Class="WPFDevelopers.Samples.ExampleViews.BarrageExample" ?????????????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ?????????????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ?????????????xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"? ?????????????xmlns:d="http://schemas.microsoft.com/expression/blend/2008"? ?????????????xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers" ?????????????xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews" ?????????????mc:Ignorable="d"? ?????????????d:DesignHeight="450"?d:DesignWidth="800"> ????<Grid> ????????<Grid.RowDefinitions> ????????????<RowDefinition/> ????????????<RowDefinition?Height="Auto"/> ????????</Grid.RowDefinitions> ????????<Canvas?Name="MyCanvas"?Background="Transparent"> ????????</Canvas> ????????<Grid?Grid.Row="1"?Name="MyGrid"> ????????????<Grid.ColumnDefinitions> ????????????????<ColumnDefinition/> ????????????????<ColumnDefinition?Width="Auto"/> ????????????</Grid.ColumnDefinitions> ????????????<TextBox?wpfdev:ElementHelper.IsWatermark="True" ?????????????????????x:Name="tbBarrage" ?????????????????????wpfdev:ElementHelper.Watermark="請彈幕內(nèi)容"/> ????????????<Button?Grid.Column="1"?Style="{StaticResource?PrimaryButton}" ????????????????????Content="發(fā)射彈幕"?Margin="4,0,0,0"? ????????????????????Click="ButtonBase_OnClick"/> ????????</Grid> ????</Grid> </UserControl>
2) 邏輯BarrageExample.xaml.cs如下:
using?System; using?System.Collections.Generic; using?System.Windows; using?System.Windows.Controls; using?System.Windows.Media; using?System.Windows.Media.Animation; namespace?WPFDevelopers.Samples.ExampleViews { ????///?<summary> ????///?BarrageExample.xaml?的交互邏輯 ????///?</summary> ????public?partial?class?BarrageExample?:?UserControl ????{ ????????private?Dictionary<TimeSpan,?List<Border>>?_dicBorder; ????????private?long?_num,?_index; ????????private?double?_right,?_top; ????????private?Random?_random?=?new?Random(); ????????public?BarrageExample() ????????{ ????????????InitializeComponent(); ????????????_dicBorder?=?new?Dictionary<TimeSpan,?List<Border>>(); ????????????Loaded?+=?delegate ????????????{ ????????????????_num?=?(int)(ActualHeight?-?MyGrid.ActualHeight)?/?40; ????????????????var?list?=?new?List<string>(); ????????????????list.Add("2333"); ????????????????list.Add("測試彈幕"); ????????????????list.Add("很難開心"); ????????????????list.Add("map"); ????????????????list.Add("map加載"); ????????????????list.Add("bing"); ????????????????list.Add("地圖"); ????????????????foreach?(var?item?in?list) ????????????????{ ????????????????????SolidColorBrush?brush?=?new?SolidColorBrush(Color.FromRgb((byte)_random.Next(1,?255), ????????????????????????(byte)_random.Next(1,?255),?(byte)_random.Next(1,?233))); ????????????????????AddBarrage(brush.Color,?item); ????????????????} ????????????}; ????????} ????????void?AddBarrage(Color?color,?string?text) ????????{ ????????????_index++; ????????????TimeSpan?time?=?default; ????????????var?linearGradientBrush?=?new?LinearGradientBrush() ????????????{ ????????????????StartPoint?=?new?Point(0,?0), ????????????????EndPoint?=?new?Point(1,?1), ????????????????MappingMode?=?BrushMappingMode.RelativeToBoundingBox, ????????????????GradientStops?=?new?GradientStopCollection ????????????????{ ????????????????????new?GradientStop?{?Color?=?Colors.Transparent,?Offset?=?2}, ????????????????????new?GradientStop?{?Color?=?color?}, ????????????????}, ????????????}; ????????????var?border?=?new?Border() ????????????{ ????????????????Background?=?linearGradientBrush, ????????????????Height?=?40, ????????????????CornerRadius?=?new?CornerRadius(20), ????????????????Padding?=?new?Thickness(40,?0,?40,?0) ????????????}; ????????????var?textBlock?=?new?TextBlock() ????????????{ ????????????????Text?=?text, ????????????????Foreground?=?Brushes.White, ????????????????VerticalAlignment?=?VerticalAlignment.Center, ????????????}; ????????????border.Child?=?textBlock; ????????????MyCanvas.Children.Add(border); ????????????border.Loaded?+=?delegate ????????????{ ????????????????time?=?TimeSpan.FromMilliseconds(border.ActualWidth?*?60); ????????????????_right?=?_right?==?0???ActualWidth?+?border.ActualWidth?:?_right; ????????????????var?y?=?ActualHeight?-?MyGrid.ActualHeight?-?border.ActualHeight; ????????????????_top?=?_top?+?40?>=?y???border.ActualHeight?:?_top; ????????????????Canvas.SetLeft(border,?_right); ????????????????Canvas.SetTop(border,?_top); ????????????????var?doubleAnimation?=?new?DoubleAnimation ????????????????{ ????????????????????From?=?_right, ????????????????????To?=?-(ActualWidth?+?border.ActualWidth), ????????????????????Duration?=?time ????????????????}; ????????????????doubleAnimation.Completed?+=?(s,?e)?=> ????????????????{ ????????????????????var?animationClock?=?s?as?AnimationClock; ????????????????????if?(animationClock?==?null)?return; ????????????????????var?duration?=?animationClock.Timeline.Duration; ????????????????????var?bordersList?=?new?List<Border>(); ????????????????????_dicBorder.TryGetValue(duration.TimeSpan,?out?bordersList); ????????????????????if?(bordersList?!=?null?&&?bordersList.Count?>?0) ????????????????????{ ????????????????????????foreach?(var?item?in?bordersList) ????????????????????????{ ????????????????????????????MyCanvas.Children.Remove(item); ????????????????????????} ????????????????????????_dicBorder.Remove(duration.TimeSpan); ????????????????????} ????????????????}; ????????????????border.BeginAnimation(Canvas.LeftProperty,?doubleAnimation); ????????????????_top?+=?border.ActualHeight?+?20; ????????????????if?(!_dicBorder.ContainsKey(time)) ????????????????????_dicBorder.Add(time,?new?List<Border>?{?border?}); ????????????????else ????????????????{ ????????????????????var?bordersList?=?new?List<Border>(); ????????????????????_dicBorder.TryGetValue(time,?out?bordersList); ????????????????????bordersList.Add(border); ????????????????} ????????????}; ????????????if?(_index?>?_num) ????????????{ ????????????????_index?=?0; ????????????} ????????} ????????private?void?ButtonBase_OnClick(object?sender,?RoutedEventArgs?e) ????????{ ????????????SolidColorBrush?brush?=?new?SolidColorBrush(Color.FromRgb((byte)_random.Next(1,?255), ????????????????(byte)_random.Next(1,?255),?(byte)_random.Next(1,?233))); ????????????AddBarrage(brush.Color,?tbBarrage.Text); ????????} ????} }
以上就是基于WPF實(shí)現(xiàn)彈幕效果的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于WPF彈幕的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#實(shí)現(xiàn)網(wǎng)絡(luò)小程序的步驟詳解
經(jīng)常要檢測某些IP地址范圍段的計(jì)算機(jī)是否在線。有很多的方法,比如進(jìn)入到網(wǎng)關(guān)的交換機(jī)上去查詢、使用現(xiàn)成的工具或者編寫一個(gè)簡單的DOS腳本等等,這些都比較容易實(shí)現(xiàn)。本文將用C#來實(shí)現(xiàn),感興趣的可以了解一下2022-12-12C#實(shí)現(xiàn)在應(yīng)用程序間發(fā)送消息的方法示例
這篇文章主要介紹了C#實(shí)現(xiàn)在應(yīng)用程序間發(fā)送消息的方法,結(jié)合具體實(shí)例形式分析了C#實(shí)現(xiàn)項(xiàng)目之間信息發(fā)送、接收等交互操作相關(guān)技巧,需要的朋友可以參考下2017-06-06C#利用Openxml讀取Excel數(shù)據(jù)實(shí)例
這篇文章主要介紹了C#利用Openxml讀取Excel數(shù)據(jù)的方法,包括使用中的注意點(diǎn)分析及疑難探討,需要的朋友可以參考下2014-09-09