WPF数字滚动效果
和WPF数字滚动抽奖有区别,WPF数字滚动抽奖是随机的,而这里是确定的。
为了系统演示,这个效果通宵加班写了整整6个小时,中间就上了次厕所。
代码:
RollingNumberItemCtrl.xaml代码:
<UserControl x:Class="SunCreate.Common.Controls.RollingNumberItemCtrl" 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" mc:Ignorable="d" d:DesignHeight="50" d:DesignWidth="300"> <Grid> <Grid Height="{Binding Height}" Width="{Binding Width}" ClipToBounds="True"> <StackPanel x:Name="stackPanel" Width="{Binding Width}" HorizontalAlignment="Center" Margin="{Binding MarginTop}" > <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="0" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="1" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="2" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="3" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="4" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="5" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="6" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="7" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="8" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="9" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="0" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="1" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="2" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="3" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="4" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="5" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="6" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="7" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="8" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> <Border Width="{Binding Width}" Height="{Binding Height}"> <TextBlock FontSize="{Binding Height}" Text="9" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> </StackPanel> </Grid> </Grid> </UserControl>
RollingNumberItemCtrl.xaml.cs代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace SunCreate.Common.Controls { /// <summary> /// NumCtrl.xaml 的交互逻辑 /// </summary> public partial class RollingNumberItemCtrl : INotifyPropertyChanged { private Thickness _MarginTop = new Thickness(0, 0, 0, 0); /// <summary> /// Margin /// </summary> public Thickness MarginTop { get { return _MarginTop; } set { _MarginTop = value; OnPropertyChanged("MarginTop"); } } private double _Num; /// <summary> /// 数字 /// </summary> public double Num { get { return _Num; } set { var ease = new ExponentialEase() { EasingMode = EasingMode.EaseOut, }; ThicknessAnimation animation = new ThicknessAnimation(); animation.EasingFunction = ease; animation.From = new Thickness(0, 0 - _Num * Height, 0, 0); double top1 = MarginTop.Top; double d = 0 - value * Height; if (value < _Num) { d = 0 - (value + 10) * Height; } _Num = value; OnPropertyChanged("Num"); MarginTop = new Thickness(0, d, 0, 0); double top2 = MarginTop.Top; animation.To = MarginTop; //animation.Duration = TimeSpan.FromMilliseconds((top1 - top2) * 10); if (top1 != top2) { animation.Duration = TimeSpan.FromMilliseconds(1500); this.stackPanel.BeginAnimation(StackPanel.MarginProperty, animation); } MarginTop = new Thickness(0, 0 - value * Height, 0, 0); } } public RollingNumberItemCtrl() { InitializeComponent(); this.DataContext = this; } #region INotifyPropertyChanged接口 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string name) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(name)); } } #endregion } }
RollingNumberCtrl.xaml代码:
<UserControl x:Class="SunCreate.Common.Controls.RollingNumberCtrl" 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" mc:Ignorable="d" xmlns:local="clr-namespace:SunCreate.Common.Controls" d:DesignHeight="30" d:DesignWidth="300" Loaded="UserControl_Loaded"> <Grid> <StackPanel x:Name="stackPanel" Orientation="Horizontal" > <local:RollingNumberItemCtrl Height="30" Width="18" Num="0" Visibility="Collapsed"></local:RollingNumberItemCtrl> <local:RollingNumberItemCtrl Height="30" Width="18" Num="0" Visibility="Collapsed"></local:RollingNumberItemCtrl> <local:RollingNumberItemCtrl Height="30" Width="18" Num="0" Visibility="Collapsed"></local:RollingNumberItemCtrl> <local:RollingNumberItemCtrl Height="30" Width="18" Num="0" Visibility="Collapsed"></local:RollingNumberItemCtrl> <local:RollingNumberItemCtrl Height="30" Width="18" Num="0" Visibility="Collapsed"></local:RollingNumberItemCtrl> <local:RollingNumberItemCtrl Height="30" Width="18" Num="0" Visibility="Collapsed"></local:RollingNumberItemCtrl> <local:RollingNumberItemCtrl Height="30" Width="18" Num="0" Visibility="Collapsed"></local:RollingNumberItemCtrl> <local:RollingNumberItemCtrl Height="30" Width="18" Num="0" Visibility="Collapsed"></local:RollingNumberItemCtrl> <local:RollingNumberItemCtrl Height="30" Width="18" Num="0"></local:RollingNumberItemCtrl> </StackPanel> </Grid> </UserControl>
RollingNumberCtrl.xaml.cs代码:
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace SunCreate.Common.Controls { /// <summary> /// MyTextBlock.xaml 的交互逻辑 /// </summary> public partial class RollingNumberCtrl : INotifyPropertyChanged { private bool _firstLoaded = true; public double ItemHeight { get { return (double)this.GetValue(RollingNumberCtrl.ItemHeightProperty); } set { this.SetValue(RollingNumberCtrl.ItemHeightProperty, value); } } private static DependencyProperty ItemHeightProperty = DependencyProperty.Register("ItemHeight", typeof(double), typeof(RollingNumberCtrl)); public string NumStr { get { return (string)this.GetValue(RollingNumberCtrl.NumStrProperty); } set { this.SetValue(RollingNumberCtrl.NumStrProperty, value); } } private static DependencyProperty NumStrProperty = DependencyProperty.Register("NumStr", typeof(string), typeof(RollingNumberCtrl), new PropertyMetadata(null, new PropertyChangedCallback(NumStrChanged))); private static void NumStrChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { (sender as RollingNumberCtrl).UpdateNumStr((sender as RollingNumberCtrl).NumStr); } private void UpdateNumStr(string numStr) { Text = numStr; } private string _Text; /// <summary> /// 文本 /// </summary> public string Text { get { return _Text; } set { _Text = value; OnPropertyChanged("Text"); if (!_firstLoaded) { RollingNumberItemCtrl[] numArr = new RollingNumberItemCtrl[stackPanel.Children.Count]; int index = 1; foreach (RollingNumberItemCtrl num in stackPanel.Children) { numArr[numArr.Length - index++] = num; } if (_Text != null) { int i = 0; foreach (char c in _Text.Reverse()) { double d = Convert.ToInt32(c - 48); ; numArr[i++].Num = d; } for (int k = 0; k < i; k++) { numArr[k].Visibility = Visibility.Visible; } for (int k = i; k < numArr.Length; k++) { numArr[k].Visibility = Visibility.Collapsed; } } } } } public RollingNumberCtrl() { InitializeComponent(); } #region INotifyPropertyChanged接口 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string name) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(name)); } } #endregion private void UserControl_Loaded(object sender, RoutedEventArgs e) { if (_firstLoaded) _firstLoaded = false; foreach (RollingNumberItemCtrl num in stackPanel.Children) { num.Height = this.ItemHeight; num.Width = this.ItemHeight * 0.6; num.FontWeight = this.FontWeight; } Text = NumStr; } } }
如何使用:
<controls:RollingNumberCtrl Margin="0 2 0 0" ItemHeight="20" NumStr="{Binding CarInOut}" Foreground="#fff" FontSize="20" FontWeight="Bold" ></controls:RollingNumberCtrl>
效果图: