基于WPF实现弹幕效果的示例代码

 更新时间:2022年09月13日 10:57:24   作者:驚鏵  
这篇文章主要为大家详细介绍了如何利用WPF实现弹幕效果,文中的示例代码讲解详细,对我们学习或工作有一定帮助,感兴趣的小伙伴可以了解一下

WPF 实现弹幕效果

框架使用大于等于.NET40

Visual Studio 2022;

项目使用 MIT 开源许可协议;

此篇代码目的只是为了分享思路

实现基础弹幕一定是要使用Canvas比较简单,只需实现Left动画从右到左。

  • 弹幕消息使用Border做弹幕背景。
  • 内容使用TextBlock做消息文本展示。
  • 当动画执行完成默认移除Canvas中的弹幕控件。
  • 使用这种方式去加载弹幕GPU会占较高。

1) 准备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="请弹幕内容"/>
            <Button Grid.Column="1" Style="{StaticResource PrimaryButton}"
                    Content="发射弹幕" 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实现弹幕效果的示例代码的详细内容,更多关于WPF弹幕的资料请关注脚本之家其它相关文章!

相关文章

  • C#实现网络小程序的步骤详解

    C#实现网络小程序的步骤详解

    经常要检测某些IP地址范围段的计算机是否在线。有很多的方法,比如进入到网关的交换机上去查询、使用现成的工具或者编写一个简单的DOS脚本等等,这些都比较容易实现。本文将用C#来实现,感兴趣的可以了解一下
    2022-12-12
  • C# 调用外部exe的三种方式

    C# 调用外部exe的三种方式

    调用外部exe是常用的功能,本文主要介绍了C# 调用外部exe的三种方式,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2024-04-04
  • C#实现在应用程序间发送消息的方法示例

    C#实现在应用程序间发送消息的方法示例

    这篇文章主要介绍了C#实现在应用程序间发送消息的方法,结合具体实例形式分析了C#实现项目之间信息发送、接收等交互操作相关技巧,需要的朋友可以参考下
    2017-06-06
  • C#实现一键清空控件值的示例代码

    C#实现一键清空控件值的示例代码

    这篇文章主要为大家详细介绍了如何利用C#语言实现一键清空控件值的功能,文中的示例代码讲解详细,对我们学习C#有一定帮助,需要的可以参考一下
    2022-09-09
  • C#利用Openxml读取Excel数据实例

    C#利用Openxml读取Excel数据实例

    这篇文章主要介绍了C#利用Openxml读取Excel数据的方法,包括使用中的注意点分析及疑难探讨,需要的朋友可以参考下
    2014-09-09
  • C#四舍五入(函数)用法实例

    C#四舍五入(函数)用法实例

    这篇文章主要介绍了C#四舍五入(函数)用法实例,有需要的朋友可以参考一下
    2013-11-11
  • C#线程倒计时器源码分享

    C#线程倒计时器源码分享

    这篇文章主要为大家分享了C#线程倒计时器源码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • 详解C# 不能用于文件名的字符

    详解C# 不能用于文件名的字符

    在 Windows 有一些字符是不能作为文件名,尝试重命名一个文件,输入/ 就可以看到windows 提示的不能作为文件名的字符,那么具体是包括哪些符号不能作为文件名呢?下面小编给大家介绍下
    2018-02-02
  • C#中增强类功能的几种方式详解

    C#中增强类功能的几种方式详解

    这篇文章主要给大家介绍了关于C#中增强类功能的几种方式的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2018-12-12
  • C#中is与as的区别分析

    C#中is与as的区别分析

    这篇文章主要介绍了C#中is与as的区别,较为详细的分析了is与as的原理与特性及用法区别,具有很好的学习借鉴价值,需要的朋友可以参考下
    2014-10-10

最新评论