SkiaSharp 自绘弹幕效果
框架使用.NET60
;
Visual Studio 2022
;
项目使用 MIT 开源许可协议;
接着上一篇 wpF 弹幕
上期有网友建议使用Skia实现弹幕。
- 弹幕消息使用
SKElement
做弹幕展现,然后在SKCanvas
进行绘制弹幕。 - 由于需要绘制矩形与文本所以需要使用到
SKBitmap
进行绘制弹幕类。 - 创建
SKBitmap
设置宽(根据文本的长度定义宽度)与高度40
。 - 创建对象
SKCanvas
并实例化的时候将SKBitmap
传入,然后对SKCanvas
进行绘制背景DrawRoundRect
与文本DrawText
,使用属性记录X
与Y
的值方便在动画的时候让弹幕动起来。 Barrage
在Render
的时候进行绘制弹幕图片DrawImage(SKBitmap,x,y)
。- 弹幕每次移动多少值 等于
SKCanvas
的宽除以弹幕的宽
。 - 当弹幕移动
Move()
时如超过-Width
则通过out
返回GUID
就移除弹幕对象。
实现代码
1) 准备 MsgInfo 弹幕消息类如下:
usingSystem; usingSkiaSharp; namespaceSkiaSharpBarrage { ///<summary> ///msginfo ///</summary> publicclassMsgInfo { privatestring_msg; publicstringGUID; publicmsgInfo(stringmsg,SKTypeface_font,floatWindowsWidth) { _msg=msg; var_random=newRandom(); varskColor=newSKColor((byte)_random.Next(1,255), (byte)_random.Next(1,255),(byte)_random.Next(1,233)); usingvarpaint=newSKPaint { Color=skColor, Style=SKPaintStyle.Fill, IsAntialias=true, StrokeWidth=2 }; paint.Shader=SKShader.CreateLinearGradient( newSKPoint(0,0), newSKPoint(1,1), new[]{SKColors.Transparent,skColor}, newfloat[]{0,1}, SKShaderTileMode.Repeat); usingvarpaintText=newSKPaint { Color=SKColors.White, IsAntialias=true, Typeface=_font, TextSize=24 }; vartextBounds=newSKRect(); paintText.MeasureText(msg,reftextBounds); varwidth=textBounds.Width+100; SKImageskImage; using(varbitmap=newSKBitmap((int)width,40,true)) using(varcanvas=newSKCanvas(bitmap)) { canvas.DrawRoundRect(0,0,width,40,20,20,paint); canvas.DrawText(msg,width/2-textBounds.Width/2,bitmap.Height/2+textBounds.HeigampRUht/2, paintText); varimage=SKImage.FromBitmap(bitmap); skImage=image; } SKImage=skImage; Width=width; X=windowsWidth+Width; CanvasWidth=windowsWidth; CostTime=TimeSpan.FromMilliseconds(Width); GUID=Guid.NewGuid().ToString("N"); } publicfloatX{get;set;} publicfloatY{get;set;} publicfloatWidth{get;set;} publicfloatCanvasWidth{get;set;} publicSKImageSKImage{get;set;} publicfloatMoveNum=>CanvasWidth/(float)CostTime.TotalMilliseconds; publicTimeSpanCostTime{get;set;} ///<summary> ///定时调用,移动指定距离 ///</summary> publicvoidMove(outstringguid) { guid=string.Empty; X=X-MoveNum; if(X<=-Width) guid=GUID; } } }
2) 新建 Barrage.cs 类如下:
usingSystem.Collections.Generic; usingSystem.Linq; usingSkiaSharp; namespaceSkiaSharpBarrage { publicclassBarrage { privatereadonlySKTypeface_font; privatereadonlyList<MsgInfo>_MsgInfo; privateint_num,_index; privatedouble_right,_top; privatefloat_width; privatereadonlyandroidfloat_height; publicBarrage(SKTypefacefont,floatwidth,floatheight,List<string>strList) { _width=width; _height=height; _font=font; _num=(int)height/40; _MsgInfo=newList<MsgInfo>(); foreach(variteminstrList)BuildMsgInfo(item); } privatevoidBuildMsgInfo(stringtext) { _index++; if(_right!=0) _width=(float)_right; varmodel=newMsgInfo(text,_font,_width); _right=_right==0?_height+model.Width:_right; vary=_height-40; _top=_top+40>=y?40:_top; model.Y=(float)_top; _MsgInfo.Add(model); _top+=60; } publicvoidAddBarrage(stringtext) { BuildMsgInfo(text); } publicvoidRender(SKCanvascanvas,SKTypefacefont,intwidth,intheight,List<string>strList) { for(vari=0;i<_MsgInfo.Count;i++) { varinfo=_MsgInfo[i]; varguid=string.Empty; info.Move(outguid); if(!string.IsNullOrEmpty(guid)) { varmodel=_MsgInfo.FirstOrDefault(x=>x.GUID==guid); _MsgInfo.Remove(model); } canvas.DrawImage(info.SKImage,info.X,info.Y); } } } }
3) MainWind开发者_开发入门ow.xaml.cs 如下:
<wpfdev:Windowx:Class="SkiaSharpBarrage.MainWindow" XMLns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers" xmlns:skia="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF" mc:Ignorable="d"WindowStartupLocation="CenterScreen" ResizeMode="CanMinimize" Title="SkiaSharpBarrage-弹幕篇"Height="450"Width="800"> <GridMargin="4"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinitionHeight="Auto"/> </Grid.RowDefinitions> <MediaElementStretch="Uniform"Grid.RowSpan="2" Name="myMediaElement"/> <skia:SKElementx:Name="skElement"/> <GridGrid.Row="1"Name="MyGrid"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinitionWidth="Auto"/> </Grid.ColumnDefinitions> <TextBoxwpfdev:ElementHelper.IsWatermark="True" x:Name="tbBarrage" wpfdev:ElementHelper.Watermark="请弹幕内容"/> <ButtonGrid.Column="1"Style="{StaticResourcePrimaryButton}" Content="发射弹幕"Margin="4,0,0,0" Click="ButtonBase_OnClick"/> </Grid> </Grid> </wpfdev:Window>
3) 逻辑 MainWinandroiddow.xaml.cs 如下:
usingSystem; usingSystem.Collections.Generic; usingSystem.IO; usingSystem.Linq; usingSystem.Threading; usingSystem.Threading.Tasks; usingSystem.Windows; usingSkiaSharp; usingSkiaSharp.Views.Desktop; namespaceSkiaSharpBarrage { ///<summary> ///InteractionlogicforMainWindow.xaml ///</summary> publicpartialclassMainWindow { privatereadonlyBarrage_barrage; privatereadonlySKTypeface_font; privatereadonlyList<string>list=newList<string>(); publicMainWindow() { list.Add("2333"); list.Add("测试弹幕公众号:WPF开发者"); list.Add("很难开心"); list.Add("LOL~"); list.Add("青春记忆"); list.Add("bing"); list.Add("Microsoft"python); InitializeComponent(); varindex=SKFontManager.Default.FontFamilies.ToList().IndexOf("微软雅黑"); _font=SKFontManager.Default.GetFontStyles(index).CreateTypeface(0); _barrage=newBarrage(_font,(float)Width,(float)Height-(float)MyGrid.ActualHeight,list); skElement.PaintSurface+=SkElement_PaintSurface; Loaded+=delegate { myMediaElement.Source= newUri(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"Leagueoflegends.mp4")); }; _=Task.Run(()=> { try { while(true) { www.devze.comDispatcher.Invoke(()=>{skElement.InvalidateVisual();}); _=SpinWait.SpinUntil(()=>false,1000/60);//每秒60帧 } } catch(Exceptione) { } }); } privatevoidSkElement_PaintSurface(object?sender,SKPaintSurfaceEventArgse) { varcanvas=e.Surface.Canvas; canvas.Clear(); _barrage.Render(canvas,_font,e.Info.Width,e.Info.Height,list); } privatevoidButtonBase_OnClick(objectsender,RoutedEventArgse) { _barrage.AddBarrage(tbBarrage.Text); } } }
实现效果
到此这篇关于WPF+SkiaSharp实现自绘弹幕效果的文章就介绍到这了,更多相关WPF SkiaSharp弹幕内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
精彩评论