欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

WPF+SkiaSharp實(shí)現(xiàn)自繪彈幕效果

 更新時(shí)間:2022年09月26日 09:44:11   作者:驚鏵  
這篇文章主要為大家詳細(xì)介紹了如何利用WPF和SkiaSharp實(shí)現(xiàn)自制彈幕效果,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,感興趣的小伙伴可以了解一下

SkiaSharp 自繪彈幕效果

框架使用.NET60

Visual Studio 2022;

項(xiàng)目使用 MIT 開源許可協(xié)議;

接著上一篇 WPF 彈幕

上期有網(wǎng)友建議使用Skia實(shí)現(xiàn)彈幕。

  • 彈幕消息使用SKElement做彈幕展現(xiàn),然后在SKCanvas進(jìn)行繪制彈幕。
  • 由于需要繪制矩形與文本所以需要使用到SKBitmap進(jìn)行繪制彈幕類。
  • 創(chuàng)建SKBitmap設(shè)置寬(根據(jù)文本的長度定義寬度)與高度40。
  • 創(chuàng)建對(duì)象SKCanvas并實(shí)例化的時(shí)候?qū)?code>SKBitmap傳入,然后對(duì)SKCanvas進(jìn)行繪制背景DrawRoundRect 與文本DrawText ,使用屬性記錄XY的值方便在動(dòng)畫的時(shí)候讓彈幕動(dòng)起來。
  • BarrageRender的時(shí)候進(jìn)行繪制彈幕圖片DrawImage(SKBitmap,x,y) 。
  • 彈幕每次移動(dòng)多少值 等于SKCanvas的寬除以彈幕的
  • 當(dāng)彈幕移動(dòng)Move()時(shí)如超過-Width則通過out返回GUID 就移除彈幕對(duì)象。

實(shí)現(xiàn)代碼

1) 準(zhǔn)備 MsgInfo 彈幕消息類如下:

using?System;
using?SkiaSharp;

namespace?SkiaSharpBarrage
{
????///?<summary>
????///?????msg?info
????///?</summary>
????public?class?MsgInfo
????{
????????private?string?_msg;

????????public?string?GUID;

????????public?MsgInfo(string?msg,?SKTypeface?_font,?float?windowsWidth)
????????{
????????????_msg?=?msg;
????????????var?_random?=?new?Random();
????????????var?skColor?=?new?SKColor((byte)?_random.Next(1,?255),
????????????????(byte)?_random.Next(1,?255),?(byte)?_random.Next(1,?233));
????????????using?var?paint?=?new?SKPaint
????????????{
????????????????Color?=?skColor,
????????????????Style?=?SKPaintStyle.Fill,
????????????????IsAntialias?=?true,
????????????????StrokeWidth?=?2
????????????};
????????????paint.Shader?=?SKShader.CreateLinearGradient(
????????????????new?SKPoint(0,?0),
????????????????new?SKPoint(1,?1),
????????????????new[]?{SKColors.Transparent,?skColor},
????????????????new?float[]?{0,?1},
????????????????SKShaderTileMode.Repeat);

????????????using?var?paintText?=?new?SKPaint
????????????{
????????????????Color?=?SKColors.White,
????????????????IsAntialias?=?true,
????????????????Typeface?=?_font,
????????????????TextSize?=?24
????????????};
????????????var?textBounds?=?new?SKRect();
????????????paintText.MeasureText(msg,?ref?textBounds);
????????????var?width?=?textBounds.Width?+?100;
????????????SKImage?skImage;
????????????using?(var?bitmap?=?new?SKBitmap((int)?width,?40,?true))
????????????using?(var?canvas?=?new?SKCanvas(bitmap))
????????????{
????????????????canvas.DrawRoundRect(0,?0,?width,?40,?20,?20,?paint);
????????????????canvas.DrawText(msg,?width?/?2?-?textBounds.Width?/?2,?bitmap.Height?/?2?+?textBounds.Height?/?2,
????????????????????paintText);
????????????????var?image?=?SKImage.FromBitmap(bitmap);
????????????????skImage?=?image;
????????????}

????????????SKImage?=?skImage;
????????????Width?=?width;
????????????X?=?windowsWidth?+?Width;
????????????CanvasWidth?=?windowsWidth;
????????????CostTime?=?TimeSpan.FromMilliseconds(Width);
????????????GUID?=?Guid.NewGuid().ToString("N");
????????}

????????public?float?X?{?get;?set;?}
????????public?float?Y?{?get;?set;?}
????????public?float?Width?{?get;?set;?}
????????public?float?CanvasWidth?{?get;?set;?}
????????public?SKImage?SKImage?{?get;?set;?}
????????public?float?MoveNum?=>?CanvasWidth?/?(float)?CostTime.TotalMilliseconds;
????????public?TimeSpan?CostTime?{?get;?set;?}

????????///?<summary>
????????///?????定時(shí)調(diào)用,移動(dòng)指定距離
????????///?</summary>
????????public?void?Move(out?string?guid)
????????{
????????????guid?=?string.Empty;
????????????X?=?X?-?MoveNum;
????????????if?(X?<=?-Width)
????????????????guid?=?GUID;
????????}
????}
}

2) 新建 Barrage.cs 類如下:

using?System.Collections.Generic;
using?System.Linq;
using?SkiaSharp;

namespace?SkiaSharpBarrage
{
????public?class?Barrage
????{
????????private?readonly?SKTypeface?_font;
????????private?readonly?List<MsgInfo>?_MsgInfo;
????????private?int?_num,?_index;
????????private?double?_right,?_top;
????????private?float?_width;
????????private?readonly?float?_height;

????????public?Barrage(SKTypeface?font,?float?width,?float?height,?List<string>?strList)
????????{
????????????_width?=?width;
????????????_height?=?height;
????????????_font?=?font;
????????????_num?=?(int)?height?/?40;
????????????_MsgInfo?=?new?List<MsgInfo>();
????????????foreach?(var?item?in?strList)?BuildMsgInfo(item);
????????}

????????private?void?BuildMsgInfo(string?text)
????????{
????????????_index++;
????????????if?(_right?!=?0)
????????????????_width?=?(float)?_right;
????????????var?model?=?new?MsgInfo(text,?_font,?_width);
????????????_right?=?_right?==?0???_height?+?model.Width?:?_right;
????????????var?y?=?_height?-?40;
????????????_top?=?_top?+?40?>=?y???40?:?_top;
????????????model.Y?=?(float)?_top;
????????????_MsgInfo.Add(model);
????????????_top?+=?60;
????????}

????????public?void?AddBarrage(string?text)
????????{
????????????BuildMsgInfo(text);
????????}

????????public?void?Render(SKCanvas?canvas,?SKTypeface?font,?int?width,?int?height,?List<string>?strList)
????????{
????????????for?(var?i?=?0;?i?<?_MsgInfo.Count;?i++)
????????????{
????????????????var?info?=?_MsgInfo[i];
????????????????var?guid?=?string.Empty;
????????????????info.Move(out?guid);
????????????????if?(!string.IsNullOrEmpty(guid))
????????????????{
????????????????????var?model?=?_MsgInfo.FirstOrDefault(x?=>?x.GUID?==?guid);
????????????????????_MsgInfo.Remove(model);
????????????????}

????????????????canvas.DrawImage(info.SKImage,?info.X,?info.Y);
????????????}
????????}
????}
}

3) MainWindow.xaml.cs 如下:

<wpfdev:Window?x: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">
????<Grid?Margin="4">
????????<Grid.RowDefinitions>
????????????<RowDefinition?/>
????????????<RowDefinition?Height="Auto"?/>
????????</Grid.RowDefinitions>
????????<MediaElement?Stretch="Uniform"?Grid.RowSpan="2"
??????????????????????Name="myMediaElement"?/>
????????<skia:SKElement?x:Name="skElement"?/>
????????<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="請(qǐng)彈幕內(nèi)容"?/>
????????????<Button?Grid.Column="1"?Style="{StaticResource?PrimaryButton}"
????????????????????Content="發(fā)射彈幕"?Margin="4,0,0,0"
????????????????????Click="ButtonBase_OnClick"?/>
????????</Grid>
????</Grid>
</wpfdev:Window>

3) 邏輯 MainWindow.xaml.cs 如下:

using?System;
using?System.Collections.Generic;
using?System.IO;
using?System.Linq;
using?System.Threading;
using?System.Threading.Tasks;
using?System.Windows;
using?SkiaSharp;
using?SkiaSharp.Views.Desktop;

namespace?SkiaSharpBarrage
{
????///?<summary>
????///?????Interaction?logic?for?MainWindow.xaml
????///?</summary>
????public?partial?class?MainWindow
????{
????????private?readonly?Barrage?_barrage;
????????private?readonly?SKTypeface?_font;
????????private?readonly?List<string>?list?=?new?List<string>();

????????public?MainWindow()
????????{
????????????list.Add("2333");
????????????list.Add("測(cè)試彈幕公眾號(hào):WPF開發(fā)者");
????????????list.Add("很難開心");
????????????list.Add("LOL~");
????????????list.Add("青春記憶");
????????????list.Add("bing");
????????????list.Add("Microsoft");
????????????InitializeComponent();
????????????var?index?=?SKFontManager.Default.FontFamilies.ToList().IndexOf("微軟雅黑");
????????????_font?=?SKFontManager.Default.GetFontStyles(index).CreateTypeface(0);
????????????_barrage?=?new?Barrage(_font,?(float)?Width,?(float)?Height?-?(float)?MyGrid.ActualHeight,?list);
????????????skElement.PaintSurface?+=?SkElement_PaintSurface;
????????????Loaded?+=?delegate
????????????{
????????????????myMediaElement.Source?=
????????????????????new?Uri(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,?"Leagueoflegends.mp4"));
????????????};
????????????_?=?Task.Run(()?=>
????????????{
????????????????try
????????????????{
????????????????????while?(true)
????????????????????{
????????????????????????Dispatcher.Invoke(()?=>?{?skElement.InvalidateVisual();?});
????????????????????????_?=?SpinWait.SpinUntil(()?=>?false,?1000?/?60);?//每秒60幀
????????????????????}
????????????????}
????????????????catch?(Exception?e)
????????????????{
????????????????}
????????????});
????????}


????????private?void?SkElement_PaintSurface(object??sender,?SKPaintSurfaceEventArgs?e)
????????{
????????????var?canvas?=?e.Surface.Canvas;
????????????canvas.Clear();
????????????_barrage.Render(canvas,?_font,?e.Info.Width,?e.Info.Height,?list);
????????}

????????private?void?ButtonBase_OnClick(object?sender,?RoutedEventArgs?e)
????????{
????????????_barrage.AddBarrage(tbBarrage.Text);
????????}
????}
}

實(shí)現(xiàn)效果

到此這篇關(guān)于WPF+SkiaSharp實(shí)現(xiàn)自繪彈幕效果的文章就介紹到這了,更多相關(guān)WPF SkiaSharp彈幕內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#獲取web.config配置文件內(nèi)容的方法

    C#獲取web.config配置文件內(nèi)容的方法

    這篇文章主要介紹了C#獲取web.config配置文件內(nèi)容的方法,涉及C#配置文件屬性獲取的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • C#后端接收form-data,創(chuàng)建實(shí)體類教程

    C#后端接收form-data,創(chuàng)建實(shí)體類教程

    這篇文章主要介紹了C#后端接收form-data,創(chuàng)建實(shí)體類教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 詳解c# 深克隆與淺克隆

    詳解c# 深克隆與淺克隆

    這篇文章主要介紹了c# 深克隆與淺克隆的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • C#網(wǎng)絡(luò)編程基礎(chǔ)之進(jìn)程和線程詳解

    C#網(wǎng)絡(luò)編程基礎(chǔ)之進(jìn)程和線程詳解

    這篇文章主要介紹了C#網(wǎng)絡(luò)編程基礎(chǔ)之進(jìn)程和線程詳解,本文對(duì)進(jìn)程、線程、線程池知識(shí)做了淺顯易懂的講解,并配有代碼實(shí)例,需要的朋友可以參考下
    2014-08-08
  • 淺談C#多線程下的調(diào)優(yōu)

    淺談C#多線程下的調(diào)優(yōu)

    本文主要介紹了C#多線程下的調(diào)優(yōu),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Unity編輯器資源導(dǎo)入處理函數(shù)OnPostprocessTexture實(shí)例深入解析

    Unity編輯器資源導(dǎo)入處理函數(shù)OnPostprocessTexture實(shí)例深入解析

    這篇文章主要為大家介紹了Unity編輯器資源導(dǎo)入處理函數(shù)OnPostprocessTexture實(shí)例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • C#中的委托、事件學(xué)習(xí)筆記

    C#中的委托、事件學(xué)習(xí)筆記

    這篇文章主要介紹了C#中的委托、事件學(xué)習(xí)筆記,本文講解了委托delegate、事件的相關(guān)知識(shí)并給出代碼實(shí)例,需要的朋友可以參考下
    2015-01-01
  • C#中try...catch的使用與常見面試題分享

    C#中try...catch的使用與常見面試題分享

    這篇文章首先給大家介紹了關(guān)于C#中try...catch的語法,而后又給大家分享了關(guān)于C#中try...catch最常見的面試題,具有一定的參考借鑒價(jià)值,需要的朋友們下面來一起看看吧。
    2017-02-02
  • C#中的Socket編程詳解

    C#中的Socket編程詳解

    本文詳細(xì)講解了C#中的Socket編程,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01
  • C#中的多線程小試牛刀

    C#中的多線程小試牛刀

    這篇文章主要給大家介紹了關(guān)于C#中多線程的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05

最新評(píng)論