WPF RotateTransform via animation and Storyboard Storyboard.SetTarget Storyboary.SetTargetProperty Begin,Pause,Resume

rotationAnimation.From = 0;
rotationAnimation.To = 360;
rotationAnimation.Duration = TimeSpan.FromSeconds(10);
rotationAnimation.RepeatBehavior = RepeatBehavior.Forever;
rotationStoryBoard.Children.Add(rotationAnimation);
Storyboard.SetTarget(rotationAnimation, linePointer);
Storyboard.SetTargetProperty(rotationAnimation,
    new PropertyPath("(Line.RenderTransform).(RotateTransform.Angle)"));
rotationStoryBoard.Begin(win, true);

 

 

 

 

 

 

 

//xaml
<Window x:Class="WpfApp222.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"
        WindowState="Maximized"
        xmlns:behavior="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:local="clr-namespace:WpfApp222"
        mc:Ignorable="d"
        Title="{Binding RotatedStr,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
        Height="450" Width="800">
    <behavior:Interaction.Triggers>
        <behavior:EventTrigger EventName="KeyDown">
            <behavior:InvokeCommandAction Command="{Binding KeyDownCommand}"
                                          PassEventArgsToCommand="True"/>
        </behavior:EventTrigger>
    </behavior:Interaction.Triggers>
    <Grid>
        <Ellipse
              Width="{Binding ElpWidth,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
              Height="{Binding ElpHeight,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
              Stroke="Red"
              StrokeThickness="10"/>

        <Line x:Name="rotateLine"
              Stroke="Red"
              StrokeThickness="10"
              StrokeStartLineCap="Round"
              StrokeEndLineCap="Triangle"
              X1="{Binding StartX,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
              Y1="{Binding StartY,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
              X2="{Binding EndX,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
              Y2="{Binding EndY,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
              RenderTransformOrigin="0.5,0.5">
            <Line.RenderTransform>
                <RotateTransform x:Name="lineRotater"/>
            </Line.RenderTransform>
        </Line>
    </Grid>
</Window>



using System.ComponentModel;
using System.Runtime.CompilerServices;
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 WpfApp222
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var vm = new MainVM(this);
            this.DataContext = vm;
        }
    }


    public class MainVM : INotifyPropertyChanged
    {
        Window win;
        FrameworkElement fe;
        private Storyboard rotationStoryBoard;
        private RotateTransform lineRotater;
        private DoubleAnimation rotationAnimation;
        private Line linePointer;
        private DateTime dtNow = DateTime.Now;
        private int loopCount = 0;
        public MainVM(Window winValue)
        {
            this.win = winValue;
            if (win != null)
            {
                win.Loaded += Win_Loaded;
                win.SizeChanged += Win_SizeChanged;
                CompositionTarget.Rendering += CompositionTarget_Rendering;
            }
        }

        ~MainVM()
        {
            CompositionTarget.Rendering -= CompositionTarget_Rendering;
        }

        private void CompositionTarget_Rendering(object? sender, EventArgs e)
        {
            if (lineRotater.Angle > 359 && DateTime.Now.Subtract(dtNow) > TimeSpan.FromSeconds(9.8))
            {
                ++loopCount;
                dtNow = DateTime.Now;
            }
            RotatedStr = $"{Math.Round(loopCount * 360 + lineRotater.Angle, 3)}";
        }

        private void Win_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            InitData();
        }

        private void Win_Loaded(object sender, RoutedEventArgs e)
        {
            InitData();
        }

        private void InitData()
        {
            var tempFe = win.Content as FrameworkElement;
            if (tempFe != null)
            {
                fe = tempFe;
                ElpWidth = fe.ActualHeight;
                ElpHeight = fe.ActualHeight;
                startX = fe.ActualWidth / 2;
                StartY = fe.ActualHeight / 2;
                EndX = fe.ActualWidth / 2;
                EndY = 15;
            }

            var tempLine = win.FindName("rotateLine") as Line;
            if (tempLine != null)
            {
                linePointer = tempLine;
            }

            var tempRotater = win.FindName("lineRotater") as RotateTransform;
            if (tempRotater != null)
            {
                lineRotater = tempRotater;
            }

            if (rotationAnimation == null)
            {
                rotationAnimation = new DoubleAnimation();
            }

            if (rotationStoryBoard == null)
            {
                rotationStoryBoard = new Storyboard();
            }
            else
            {
                rotationAnimation.From = 0;
                rotationAnimation.To = 360;
                rotationAnimation.Duration = TimeSpan.FromSeconds(10);
                rotationAnimation.RepeatBehavior = RepeatBehavior.Forever;
                rotationStoryBoard.Children.Add(rotationAnimation);
                Storyboard.SetTarget(rotationAnimation, linePointer);
                Storyboard.SetTargetProperty(rotationAnimation,
                    new PropertyPath("(Line.RenderTransform).(RotateTransform.Angle)"));
                rotationStoryBoard.Begin(win, true);
            }
        }

        public event PropertyChangedEventHandler? PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private string rotatedStr;
        public string RotatedStr
        {
            get
            {
                return rotatedStr;
            }
            set
            {
                if (rotatedStr != value)
                {
                    rotatedStr = value;
                    OnPropertyChanged();
                }
            }
        }

        private double elpWidth;
        public double ElpWidth
        {
            get
            {
                return elpWidth;
            }
            set
            {
                if (value != elpWidth)
                {
                    elpWidth = value;
                    OnPropertyChanged();
                }
            }
        }

        private double elpHeight;
        public double ElpHeight
        {
            get
            {
                return elpHeight;
            }
            set
            {
                if (value != elpHeight)
                {
                    elpHeight = value;
                    OnPropertyChanged();
                }
            }
        }

        private bool isPaused = false;
        public bool IsPaused
        {
            get
            {
                return isPaused;
            }
            set
            {
                if (value != isPaused)
                {
                    isPaused = value;
                    OnPropertyChanged();
                    OnIsPausedChanged();
                }
            }
        }

        private void OnIsPausedChanged()
        {
            if (IsPaused)
            {
                rotationStoryBoard.Pause(win);
            }
            else
            {
                rotationStoryBoard.Resume(win);
            }
        }

        private double startX;
        public double StartX
        {
            get
            {
                return startX;
            }
            set
            {
                if (value != startX)
                {
                    startX = value;
                    OnPropertyChanged();
                }
            }
        }

        private double startY;
        public double StartY
        {
            get
            {
                return startY;
            }
            set
            {
                if (value != startY)
                {
                    startY = value;
                    OnPropertyChanged();
                }
            }
        }

        private double endX;
        public double EndX
        {
            get
            {
                return endX;
            }
            set
            {
                if (value != endX)
                {
                    endX = value;
                    OnPropertyChanged();
                }
            }
        }

        private double endY;
        public double EndY
        {
            get
            {
                return endY;
            }
            set
            {
                if (value != endY)
                {
                    endY = value;
                    OnPropertyChanged();
                }
            }
        }

        private DelCommand keyDownCommand;
        public DelCommand KeyDownCommand
        {
            get
            {
                if (keyDownCommand == null)
                {
                    keyDownCommand = new DelCommand(KeyDownCommandExecuted);
                }
                return keyDownCommand;
            }
        }


        private void KeyDownCommandExecuted(object? obj)
        {
            IsPaused = !IsPaused;
        }
    }

    public class DelCommand : ICommand
    {
        private Action<object?> execute;
        private Predicate<object?> canExecute;
        public DelCommand(Action<object?> executeValue, Predicate<object?> canExecuteValue = null)
        {
            execute = executeValue;
            canExecute = canExecuteValue;
        }

        public event EventHandler? CanExecuteChanged
        {
            add
            {
                CommandManager.RequerySuggested += value;
            }
            remove
            {
                CommandManager.RequerySuggested -= value;
            }
        }

        public bool CanExecute(object? parameter)
        {
            if (canExecute == null)
            {
                return true;
            }
            return canExecute(parameter);
        }

        public void Execute(object? parameter)
        {
            execute(parameter);
        }
    }
}

 

posted @ 2025-05-03 00:28  FredGrit  阅读(13)  评论(0)    收藏  举报