WPF 实现弹幕效果

 WPF 实现弹幕效果

控件名:BarrageExample

作者:WPFDevelopersOrg

原文链接:   https://github.com/WPFDevelopersOrg/WPFDevelopers

  • 框架使用大于等于.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);}}}
de3f13afe67b4e296718bef6db5b6e43.gif

Github|BarrageExample.xaml.cs[1]
Gitee|BarrageExample.xaml.cs[2]

参考资料

[1]

Github|BarrageExample.xaml.cs: https://github.com/WPFDevelopersOrg/WPFDevelopers/blob/master/src/WPFDevelopers.Samples/ExampleViews/BarrageExample.xaml.cs

[2]

Gitee|BarrageExample.xaml.cs: https://gitee.com/WPFDevelopersOrg/WPFDevelopers/blob/master/src/WPFDevelopers.Samples/ExampleViews/BarrageExample.xaml.cs

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/282827.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF效果第一百九十八篇之模块对比

前面效果中分享了彩色马蹄图的效果和范围内拖拽;这不大假期的时间反正没啥事就在家撸代码;今天又是LisBox实现的效果,看最终效果:1、刚开始一朋友说用DataGrid来实现.首先把行对象转换成列对象,至于控制列的话,就后台重新赋值对象来控制前台.我是觉得太费劲直接放弃了;还是首选…

saltstack的状态文件

saltstack状态文件设定&#xff1a;编辑/etc/salt/master&#xff0c;修改其中关于“设置文件的目录”的设置&#xff1a;说明&#xff1a;注意语法格式&#xff0c;顶格/冒号/两个空格state_top: top.sls # The state system uses a "top" file to tell the minions…

【Shashlik.EventBus】.NET 事件总线,分布式事务最终一致性简介

分布式事务、CAP定理、事件总线&#xff0c;在当前微服务、分布式、集群大行其道的架构前提下&#xff0c;是不可逃避的几个关键字&#xff0c;在此不会过多阐述相关的理论知识。Shashlik.EventBus就是一个基于.NET6的开源事件总线解决方案&#xff0c;同时也是分布式事务最终一…

5个超实用的Visual Studio插件

工欲善其事&#xff0c;必先利其器,整理的一些我必装的5款Visual Studio插件&#xff0c;希望你们能get到。01 CodeMaidCodeMaid快速整理代码文件&#xff0c;规范你的代码&#xff0c;提高代码阅读体验。代码自动对齐&#xff0c;格式化代码&#xff08;ps&#xff1a;不用再按…

BZOJ1509: [NOI2003]逃学的小孩(树的直径)

Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1126 Solved: 567[Submit][Status][Discuss]Description Input 第一行是两个整数N&#xff08;3  N  200000&#xff09;和M&#xff0c;分别表示居住点总数和街道总数。以下M行&#xff0c;每行给出一条街道的信息。第i1行…

Lombok@Builder和@NoArgsConstructor冲突

问题 今天在使用lombok简化model类时。使用Builder建造者模式。报以下异常 解决办法。 去掉NoArgsConstructor添加AllArgsConstructor源码分析 下图是编译后的源码 只使用Builder会自动创建全参构造器。而添加上NoArgsConstructor后就不会自动产生全参构造器

ntop linux,Linux下开源监控软件Ntop的性能提升方案

摘要&#xff1a;Ntop是一款Linux下常见的开源监控软件&#xff0c;它可以监测的数据包括&#xff1a;网络流量、使用协议、系统负载、端口情况、数据包发送时间等。正常情况下它工作的时候就像一部被动声纳&#xff0c;默默的接收看来自网络的各种信息&#xff0c;通过对这些数…

性能优化8--内存泄露

一.根源&#xff1a; 内存泄露简单说就是已经没有用的资源&#xff0c;但是由于被其他资源引用着无法被GC销毁。 二.内存泄露常见场景 1.单例导致内存泄露 单例的静态特性使得它的生命周期同应用的生命周期一样长&#xff0c;如果一个对象已经没有用处了&#xff0c;但是单例还…

记一次 .NET 某打印服务 非托管内存泄漏

一&#xff1a;背景 1. 讲故事前段时间有位朋友在微信上找到我&#xff0c;说他的程序出现了内存泄漏&#xff0c;能不能帮他看一下&#xff0c;这个问题还是比较经典的&#xff0c;加上好久没上非托管方面的东西了&#xff0c;这篇就和大家分享一下&#xff0c;话不多说&#…

mysql经典的8小时问题-wait_timeout

2019独角兽企业重金招聘Python工程师标准>>> 前段时间 现网突然频繁报出 连接不上数据库&#xff0c;偶滴的妖孽&#xff0c;其他地方都是用mysql&#xff0c;也没遇到这个问题呀。 java.io.EOFExceptionat at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1913…

Chrome DevTools — Network

记录网络请求 默认情况下&#xff0c;只要DevTools在开启状态&#xff0c;DevTools会记录所有的网络请求&#xff0c;当然&#xff0c;记录都是在Network面板展示的。 停止记录网络请求 点击Stop recording network log红色图标&#xff0c;当它变为灰色时&#xff0c;表示DevT…

MySQL 查看表结构简单命令

一、简单描述表结构&#xff0c;字段类型 desc tabl_name; 显示表结构&#xff0c;字段类型&#xff0c;主键&#xff0c;是否为空等属性&#xff0c;但不显示外键。 例如&#xff1a;desc table_name 二、查询表中列的注释信息 select * from information_schema.columns wher…

简单获取任意app的URL Schemes

简单说明 最近业务需要&#xff0c;一直在查询App的scheme相关信息&#xff0c;找到一种比较可靠的方法&#xff0c;分享给大家 步骤如下&#xff1a; 在电脑上使用iTunes下载那个app下载完后&#xff0c;在itunes里点击这个app&#xff0c;选择->Show in Finder&#xff0c…

Dnslog在SQL注入中的利用

参考文献&#xff1a;www.anquanke.com/post/id/98096https://bbs.pediy.com/thread-223881.htm DNSlog在Web攻击的利用 在某些无法直接利用漏洞获得回显的情况下&#xff0c;但是目标可以发起DNS请求&#xff0c;这个时候就可以通过DNSlog把想获得的数据外带出来。 常用情况 S…

让泛型的思维扎根在脑海——深刻理解泛型

1.前言往往一些刚接触C#编程的初学者&#xff0c;对于泛型的认识就是直接跳到对泛型集合的使用上&#xff0c;虽然微软为我们提供了很多内置的泛型类型&#xff0c;但是如果我们只是片面的了解调用方式&#xff0c;这会导致我们对泛型盲目的使用。至于为什么要使用泛型&#xf…

android 系统ui修改器,分享两个效果 - Android 系统 UI 管理

SystemUIManage.gifDimming the System Bars (沉浸模式)知乎 和 Medium 中都使用到了这个效果&#xff0c;作为沉浸式阅读模式。// This example uses decor view, but you can use any visible view.View decorView getWindow().getDecorView();int uiOptions View.SYSTEM_U…

打游戏要存进度-备忘录模式

打游戏要存进度-备忘录模式 学习自 《大话设计模式》 备忘录模式漫谈 备忘录的这种设计思想是非常常见的&#xff0c;比如说围棋游戏的悔棋&#xff0c;绘图软件的撤销功能等等&#xff0c;都或多或少的使用了备忘录模式来处理对象的状态。 备忘录(Memento): 在不破坏封装性的前…

利用lay-ui结合ajax实现分页功能(不借助框架,简单易懂)

效果图: 1.创建html页面 01.html(前台文件) 2.创建index.php(后台文件) ------------------热身结束,开始正式分页之旅------------------ 3.在html页面中引入layui需要用到的css以及js,还有我们自己额外需要用到的jquery 4.在html文件中,将基本的分页栏显示出来 5.好啦,htm…

酷派手机android版本,系统版本迎来升级

系统版本迎来升级这个应该是两个版本之间最大但是却不那么直观的不同了&#xff0c;因为从TD版酷派大神F1采用的CoolLife UI 5.0版本&#xff0c;再到联通版酷派大神F1所搭载的CoolLife UI 5.5版本&#xff0c;它们之间经历了一个比较不错的升级。在图标ICON&#xff0c;功能设…

最终用户计算安全——特权访问控制

本篇算是系列的第二篇&#xff0c;之前写了一篇关于勒索软件攻击的&#xff0c;坦白说写这样的文很费脑子&#xff0c;而且喜欢看的读者估计也不多…不过我觉得整理一下思路&#xff0c;对于通过最终用户计算产品或方案来提升组织安全还是有很大的意义的。所以一边喝着清茶吃着…