123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- using System;
- using System.ComponentModel;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Media;
- using System.Windows.Media.Animation;
- using System.Windows.Media.Media3D;
- using HandyControl.Data;
- namespace HandyControl.Controls;
- public class FlipNumber : Viewport3D
- {
- private bool _isLoaded;
- private TextBlock _page1TextDown;
- private TextBlock _page2TextUp;
- private TextBlock _page2TextDown;
- private TextBlock _page3TextUp;
- private ContainerUIElement3D _page1;
- private ContainerUIElement3D _page2;
- private ContainerUIElement3D _page3;
- private ContainerUIElement3D _content;
- private readonly AxisAngleRotation3D _pageRotation3D;
- private readonly DoubleAnimation _animation;
- private bool _isAnimating;
- public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register(
- nameof(CornerRadius), typeof(CornerRadius), typeof(FlipNumber), new PropertyMetadata(new CornerRadius(4)));
- public CornerRadius CornerRadius
- {
- get => (CornerRadius) GetValue(CornerRadiusProperty);
- set => SetValue(CornerRadiusProperty, value);
- }
- public static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register(
- nameof(Background), typeof(Brush), typeof(FlipNumber), new PropertyMetadata(default(Brush)));
- public Brush Background
- {
- get => (Brush) GetValue(BackgroundProperty);
- set => SetValue(BackgroundProperty, value);
- }
- public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register(
- nameof(Foreground), typeof(Brush), typeof(FlipNumber), new PropertyMetadata(default(Brush)));
- public Brush Foreground
- {
- get => (Brush) GetValue(ForegroundProperty);
- set => SetValue(ForegroundProperty, value);
- }
- public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register(
- nameof(FontSize), typeof(double), typeof(FlipNumber), new PropertyMetadata(70.0));
- [TypeConverter(typeof(FontSizeConverter))]
- public double FontSize
- {
- get => (double) GetValue(FontSizeProperty);
- set => SetValue(FontSizeProperty, value);
- }
- public static readonly DependencyProperty NumberProperty = DependencyProperty.Register(
- nameof(Number), typeof(int), typeof(FlipNumber), new PropertyMetadata(ValueBoxes.Int0Box, OnNumberChanged));
- private static void OnNumberChanged(DependencyObject s, DependencyPropertyChangedEventArgs e) =>
- ((FlipNumber) s).OnNumberChanged();
- public int Number
- {
- get => (int) GetValue(NumberProperty);
- set => SetValue(NumberProperty, value);
- }
- public FlipNumber()
- {
- var visual3D = new ModelVisual3D
- {
- Content = new DirectionalLight()
- };
- Children.Add(visual3D);
- _pageRotation3D = new AxisAngleRotation3D
- {
- Angle = 0,
- Axis = new Vector3D(1, 0, 0)
- };
- _animation = new DoubleAnimation(0, 180, new Duration(TimeSpan.FromSeconds(0.8)))
- {
- FillBehavior = FillBehavior.Stop
- };
- _animation.Completed += Animation_Completed;
- Loaded += (s, e) =>
- {
- if (_isLoaded) return;
- _isLoaded = true;
- InitNumber();
- var transform3D = new RotateTransform3D(_pageRotation3D);
- _page2.Transform = transform3D;
- };
- }
- private void Animation_Completed(object sender, EventArgs e)
- {
- _isAnimating = false;
- UpdateNumber();
- }
- private void InitNumber()
- {
- _page1 = new ContainerUIElement3D();
- var num1 = Number > 8 ? 0 : Number + 1;
- var page1NumDown = CreateNumber(num1, false, out _page1TextDown);
- _page1.Children.Add(page1NumDown);
- _page2 = new ContainerUIElement3D();
- var page2NumUp = CreateNumber(num1, true, out _page2TextUp);
- var page2NumDown = CreateNumber(Number, false, out _page2TextDown);
- _page2.Children.Add(page2NumUp);
- _page2.Children.Add(page2NumDown);
- _page3 = new ContainerUIElement3D();
- var page3NumUp = CreateNumber(Number, true, out _page3TextUp);
- _page3.Children.Add(page3NumUp);
- var transform3D = new RotateTransform3D(new AxisAngleRotation3D
- {
- Angle = 180,
- Axis = new Vector3D(1, 0, 0)
- });
- _page3.Transform = transform3D;
- _content = new ContainerUIElement3D
- {
- Children =
- {
- _page1,
- _page2,
- _page3
- }
- };
- Children.Add(_content);
- }
- private bool CheckNull() => _page1TextDown != null && _page2TextUp != null && _page2TextDown != null && _page3TextUp != null;
- private void OnNumberChanged()
- {
- if (!CheckNull()) return;
- InitNewNumber();
- if (_isAnimating)
- {
- _isAnimating = false;
- UpdateNumber();
- return;
- }
- _isAnimating = true;
- _pageRotation3D.BeginAnimation(AxisAngleRotation3D.AngleProperty, _animation);
- }
- private void InitNewNumber()
- {
- var num1 = Number.ToString();
- _page1TextDown.Text = num1;
- _page2TextUp.Text = num1;
- }
- private void UpdateNumber()
- {
- _pageRotation3D.BeginAnimation(AxisAngleRotation3D.AngleProperty, null);
- _pageRotation3D.Angle = 0;
- var num = Number.ToString();
- _page2TextDown.Text = num;
- _page3TextUp.Text = num;
- _isAnimating = false;
- }
- private Viewport2DVisual3D CreateNumber(int num, bool isUp, out TextBlock textBlock)
- {
- int flag;
- var rotateTransform = new RotateTransform();
- if (isUp)
- {
- flag = -1;
- rotateTransform.Angle = 180;
- }
- else
- {
- flag = 1;
- }
- var halfWidth = ActualWidth / 2;
- var quarterWidth = ActualWidth / 4;
- var quarterHeight = ActualHeight / 4;
- var meMaterial = new DiffuseMaterial();
- Viewport2DVisual3D.SetIsVisualHostMaterial(meMaterial, true);
- textBlock = new TextBlock
- {
- RenderTransformOrigin = new Point(0.5, 0.5),
- Foreground = Foreground,
- FontSize = FontSize,
- VerticalAlignment = VerticalAlignment.Center,
- HorizontalAlignment = HorizontalAlignment.Center,
- TextAlignment = TextAlignment.Center,
- Text = num.ToString(),
- RenderTransform = rotateTransform,
- Margin = new Thickness(0, 0, 0, -quarterHeight),
- FontFamily = new FontFamily("Consolas")
- };
- var border = new Border
- {
- ClipToBounds = true,
- CornerRadius = new CornerRadius(CornerRadius.TopLeft, CornerRadius.TopRight, 0, 0),
- Background = Background,
- Width = halfWidth,
- Height = quarterHeight,
- Child = textBlock
- };
- var positions = new Point3DCollection
- {
- new(-quarterWidth * flag, quarterHeight, 0),
- new(-quarterWidth * flag, 0, 0),
- new(quarterWidth * flag, 0, 0),
- new(quarterWidth * flag, quarterHeight, 0)
- };
- var triangleIndices = new Int32Collection
- {
- 0,
- 1,
- 2,
- 0,
- 2,
- 3
- };
- var textureCoordinates = new PointCollection
- {
- new(0, 0),
- new(0, 1),
- new(1, 1),
- new(1, 0)
- };
- var geometry3D = new MeshGeometry3D
- {
- Positions = positions,
- TriangleIndices = triangleIndices,
- TextureCoordinates = textureCoordinates
- };
- var child = new Viewport2DVisual3D
- {
- Geometry = geometry3D,
- Visual = border,
- Material = meMaterial
- };
- return child;
- }
- }
|