如何在C#中为画布上的线设置动画?

时间:2013-03-18 03:23:10

标签: c# wpf animation canvas line

你如何在屏幕上画一条线?

我正在尝试在C#/ WPF项目中对画布上的一行进行动画处理。

我想使用C#代码而不是XML。

感谢。

2 个答案:

答案 0 :(得分:13)

我有一个使用MVVM模式的正在运行的示例,并在ListBox内创建了Canvas作为其ItemsPanel的行。

我实际上是为this question制作的,但OP有点消失,从未与我联系。

这就是我的电脑中的样子:

enter image description here

主要部分是:

<ListBox ItemsSource="{Binding}" x:Name="lst" Height="500" Width="500">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas IsItemsHost="True"/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="FocusVisualStyle">
                        <Setter.Value>
                            <Style TargetType="Control">
                                <Setter Property="Opacity" Value="0"/>
                            </Style>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ListBoxItem">
                                <Line X1="{Binding X1}" Y1="{Binding Y1}"
                                      X2="{Binding X2}" Y2="{Binding Y2}" 
                                      StrokeThickness="{Binding Thickness}"
                                      Opacity="{Binding Opacity}"
                                      x:Name="Line">
                                    <Line.Stroke>
                                        <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                                            <GradientStop Color="{Binding Color1}" Offset="0"/>
                                            <GradientStop Color="{Binding Color2}" Offset="1"/>
                                        </LinearGradientBrush>
                                    </Line.Stroke>
                                </Line>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="true">
                                        <Setter Property="Effect" TargetName="Line">
                                            <Setter.Value>
                                                <DropShadowEffect Color="CornflowerBlue" ShadowDepth="3" BlurRadius="10"/>
                                            </Setter.Value>
                                        </Setter>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>

视图模型:

 public class LineViewModel : INotifyPropertyChanged
    {
        #region Timer-based Animation

        private System.Threading.Timer Timer;
        private static Random Rnd = new Random();

        private bool _animate;
        public bool Animate
        {
            get { return _animate; }
            set
            {
                _animate = value;
                NotifyPropertyChanged("Animate");
                if (value)
                    StartTimer();
                else
                    StopTimer();
            }
        }

        private int _animationSpeed = 1;
        public int AnimationSpeed
        {
            get { return _animationSpeed; }
            set
            {
                _animationSpeed = value;
                NotifyPropertyChanged("AnimationSpeed");
                if (Timer != null)
                    Timer.Change(0, 100/value);
            }
        }

        private static readonly List<int> _animationSpeeds = new List<int>{1,2,3,4,5};
        public List<int> AnimationSpeeds
        {
            get { return _animationSpeeds; }
        }

        public void StartTimer()
        {
            StopTimer();
            Timer = new Timer(x => Timer_Tick(), null, 0, 100/AnimationSpeed);
        }

        public void StopTimer()
        {
            if (Timer != null)
            {
                Timer.Dispose();
                Timer = null;
            }
        }

        private void Timer_Tick()
        {
            X1 = X1 + Rnd.Next(-2, 3);
            Y1 = Y1 + Rnd.Next(-2, 3);
            X2 = X2 + Rnd.Next(-2, 3);
            Y2 = Y2 + Rnd.Next(-2, 3);
        }

        #endregion

        #region Coordinates

        private double _x1;
        public double X1
        {
            get { return _x1; }
            set
            {
                _x1 = value;
                NotifyPropertyChanged("X1");
            }
        }

        private double _y1;
        public double Y1
        {
            get { return _y1; }
            set
            {
                _y1 = value;
                NotifyPropertyChanged("Y1");
            }
        }

        private double _x2;
        public double X2
        {
            get { return _x2; }
            set
            {
                _x2 = value;
                NotifyPropertyChanged("X2");
            }
        }

        private double _y2;
        public double Y2
        {
            get { return _y2; }
            set
            {
                _y2 = value;
                NotifyPropertyChanged("Y2");
            }
        }

        #endregion

        #region Other Properties

        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                NotifyPropertyChanged("Name");
            }
        }

        private double _thickness;
        public double Thickness
        {
            get { return _thickness; }
            set
            {
                _thickness = value;
                NotifyPropertyChanged("Thickness");
            }
        }

        public Color Color1 { get; set; }
        public Color Color2 { get; set; }

        private double _opacity = 1;
        public double Opacity
        {
            get { return _opacity; }
            set
            {
                _opacity = value;
                NotifyPropertyChanged("Opacity");
            }
        }

        #endregion

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                {
                    if (PropertyChanged != null)
                        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }));
        }

        #endregion
    }

修改GitHub

上的源代码

答案 1 :(得分:6)

您需要使用Storyboard并为Line.X2Line.Y2属性设置动画。看看这是否适合你。

<强> MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Canvas Name="myCanvas">
        <Button Canvas.Left="248" Canvas.Top="222" Content="Button" Height="23" Name="button1" Width="75" Click="button1_Click" />
    </Canvas>
</Window>

按钮点击活动

private void button1_Click(object sender, RoutedEventArgs e)
{
    Line line = new Line();
    myCanvas.Children.Add(line);
    line.Stroke = Brushes.Red;
    line.StrokeThickness = 2;
    line.X1 = 0;
    line.Y1 = 0;
    Storyboard sb = new Storyboard();
    DoubleAnimation da = new DoubleAnimation(line.Y2 , 100, new Duration(new TimeSpan(0, 0, 1)));
    DoubleAnimation da1 = new DoubleAnimation(line.X2, 100, new Duration(new TimeSpan(0, 0, 1)));
    Storyboard.SetTargetProperty(da, new PropertyPath("(Line.Y2)"));
    Storyboard.SetTargetProperty(da1, new PropertyPath("(Line.X2)"));
    sb.Children.Add(da);
    sb.Children.Add(da1);

    line.BeginStoryboard(sb);


}