diff --git a/AIStudio.Wpf.DiagramApp/Views/PropertyControl.xaml b/AIStudio.Wpf.DiagramApp/Views/PropertyControl.xaml
index 97ff0d5..82923bb 100644
--- a/AIStudio.Wpf.DiagramApp/Views/PropertyControl.xaml
+++ b/AIStudio.Wpf.DiagramApp/Views/PropertyControl.xaml
@@ -298,6 +298,23 @@
+
diff --git a/AIStudio.Wpf.DiagramDesigner/Enums/LineAnimation.cs b/AIStudio.Wpf.DiagramDesigner/Enums/LineAnimation.cs
new file mode 100644
index 0000000..d985ed4
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/Enums/LineAnimation.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Text;
+
+namespace AIStudio.Wpf.DiagramDesigner
+{
+ public enum LineAnimation
+ {
+ [Description("无")]
+ None,
+ [Description("路径动画")]
+ PathAnimation,
+ [Description("虚线流动")]
+ DashAnimation,
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/UserControls/DiagramControl.xaml b/AIStudio.Wpf.DiagramDesigner/UserControls/DiagramControl.xaml
index 8047cc7..53ae2a5 100644
--- a/AIStudio.Wpf.DiagramDesigner/UserControls/DiagramControl.xaml
+++ b/AIStudio.Wpf.DiagramDesigner/UserControls/DiagramControl.xaml
@@ -514,7 +514,11 @@
-
+
+
+
+
+
@@ -523,23 +527,21 @@
-
+
+
@@ -637,25 +643,12 @@
-
-
-
-
-
-
-
-
+ Value="Black" />-->
+
diff --git a/AIStudio.Wpf.DiagramDesigner/UserControls/LineControl.xaml b/AIStudio.Wpf.DiagramDesigner/UserControls/LineControl.xaml
new file mode 100644
index 0000000..e0d6ce3
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/UserControls/LineControl.xaml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
diff --git a/AIStudio.Wpf.DiagramDesigner/UserControls/LineControl.xaml.cs b/AIStudio.Wpf.DiagramDesigner/UserControls/LineControl.xaml.cs
new file mode 100644
index 0000000..e65141c
--- /dev/null
+++ b/AIStudio.Wpf.DiagramDesigner/UserControls/LineControl.xaml.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+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 AIStudio.Wpf.DiagramDesigner
+{
+ ///
+ /// LineControl.xaml 的交互逻辑
+ ///
+ public partial class LineControl : UserControl
+ {
+ public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
+ nameof(IsSelected), typeof(bool), typeof(LineControl), new FrameworkPropertyMetadata(
+ false, OnIsSelectedChanged));
+
+ private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (object.Equals(e.NewValue, true))
+ {
+ (d as LineControl).line.Stroke = Brushes.Black;
+ }
+ }
+
+ public bool IsSelected
+ {
+ get => (bool)GetValue(IsSelectedProperty);
+ set => SetValue(IsSelectedProperty, value);
+ }
+
+ public LineControl()
+ {
+ InitializeComponent();
+
+ this.Loaded += PathAnimation_Loaded;
+ this.Unloaded += LineControl_Unloaded;
+ }
+
+ private void LineControl_Unloaded(object sender, RoutedEventArgs e)
+ {
+ if (this.DataContext is ConnectorViewModel connector)
+ {
+ connector.PropertyChanged -= Connector_PropertyChanged;
+ }
+ _story?.Stop();
+ }
+
+ private async void PathAnimation_Loaded(object sender, RoutedEventArgs e)
+ {
+ if (this.DataContext is ConnectorViewModel connector)
+ {
+ connector.PropertyChanged -= Connector_PropertyChanged;
+ connector.PropertyChanged += Connector_PropertyChanged;
+ }
+ this.ball.Visibility = Visibility.Collapsed;
+ await DoAnimation();
+ }
+
+ private async void Connector_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ switch (e.PropertyName)
+ {
+ case nameof(ConnectorViewModel.LineAnimation):
+ case nameof(ConnectorViewModel.PathGeneratorResult):
+ await DoAnimation();
+ break;
+
+ }
+ }
+
+ private async Task DoAnimation()
+ {
+ if (this.DataContext is ConnectorViewModel connector && connector.IsFullConnection)
+ {
+ await System.Threading.Tasks.Task.Delay(100);
+ switch (connector.LineAnimation)
+ {
+ case LineAnimation.None:
+ _story?.Stop();
+ ball.Visibility = Visibility.Collapsed;
+ break;
+ case LineAnimation.PathAnimation:
+ PathAnimation();
+ break;
+ case LineAnimation.DashAnimation:
+ DashAnimation();
+ break;
+ }
+ }
+ }
+
+ Storyboard _story;
+
+ private void PathAnimation()
+ {
+ this.ball.Visibility = Visibility.Visible;
+
+ Canvas.SetTop(this.ball, -this.ball.ActualHeight / 2);
+ Canvas.SetLeft(this.ball, -this.ball.ActualWidth / 2);
+
+ this.ball.RenderTransformOrigin = new Point(0.5, 0.5);
+
+ TranslateTransform translate = new TranslateTransform();
+ RotateTransform rotate = new RotateTransform();
+ TransformGroup group = new TransformGroup();
+ group.Children.Add(rotate);//先旋转
+ group.Children.Add(translate);//再平移
+ this.ball.RenderTransform = group;
+
+ NameScope.SetNameScope(this, new NameScope());
+ this.RegisterName("translate", translate);
+ this.RegisterName("rotate", rotate);
+
+ DoubleAnimationUsingPath animationX = new DoubleAnimationUsingPath();
+ animationX.PathGeometry = this.line.Data?.GetFlattenedPathGeometry();
+ animationX.Source = PathAnimationSource.X;
+ animationX.Duration = new Duration(TimeSpan.FromSeconds(2));
+
+ DoubleAnimationUsingPath animationY = new DoubleAnimationUsingPath();
+ animationY.PathGeometry = this.line.Data?.GetFlattenedPathGeometry();
+ animationY.Source = PathAnimationSource.Y;
+ animationY.Duration = animationX.Duration;
+
+ DoubleAnimationUsingPath animationAngle = new DoubleAnimationUsingPath();
+ animationAngle.PathGeometry = this.line.Data?.GetFlattenedPathGeometry();
+ animationAngle.Source = PathAnimationSource.Angle;
+ animationAngle.Duration = animationX.Duration;
+
+ _story?.Stop();
+ _story = new Storyboard();
+ _story.RepeatBehavior = RepeatBehavior.Forever;
+ //story.AutoReverse = true;
+ _story.Children.Add(animationX);
+ _story.Children.Add(animationY);
+ _story.Children.Add(animationAngle);
+ Storyboard.SetTargetName(animationX, "translate");
+ Storyboard.SetTargetName(animationY, "translate");
+ Storyboard.SetTargetName(animationAngle, "rotate");
+ Storyboard.SetTargetProperty(animationX, new PropertyPath(TranslateTransform.XProperty));
+ Storyboard.SetTargetProperty(animationY, new PropertyPath(TranslateTransform.YProperty));
+ Storyboard.SetTargetProperty(animationAngle, new PropertyPath(RotateTransform.AngleProperty));
+
+ _story.Begin(this);
+
+ }
+
+ private void DashAnimation()
+ {
+ this.ball.Visibility = Visibility.Collapsed;
+
+
+ var animation = new DoubleAnimation(0, -10, new Duration(TimeSpan.FromSeconds(0.5)))
+ {
+ RepeatBehavior = RepeatBehavior.Forever,
+ };
+ Storyboard.SetTargetProperty(animation, new PropertyPath("StrokeDashOffset"));
+ Storyboard.SetTarget(animation, this.line);
+
+ _story?.Stop();
+ _story = new Storyboard();
+ _story.RepeatBehavior = RepeatBehavior.Forever;
+ _story.Children.Add(animation);
+ _story.Begin(this);
+ }
+
+ }
+}
diff --git a/AIStudio.Wpf.DiagramDesigner/UserControls/TextControl.xaml.cs b/AIStudio.Wpf.DiagramDesigner/UserControls/TextControl.xaml.cs
index d61317d..f96d9ad 100644
--- a/AIStudio.Wpf.DiagramDesigner/UserControls/TextControl.xaml.cs
+++ b/AIStudio.Wpf.DiagramDesigner/UserControls/TextControl.xaml.cs
@@ -50,6 +50,7 @@ namespace AIStudio.Wpf.DiagramDesigner
if (this.DataContext is ISelectable selectable)
{
+ selectable.PropertyChanged -= TextControl_PropertyChanged;
selectable.PropertyChanged += TextControl_PropertyChanged;
}
TextControl_PropertyChanged(this.DataContext, new System.ComponentModel.PropertyChangedEventArgs("IsSelected"));
diff --git a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/ConnectorViewModel.cs b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/ConnectorViewModel.cs
index 7507db6..2641d89 100644
--- a/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/ConnectorViewModel.cs
+++ b/AIStudio.Wpf.DiagramDesigner/ViewModels/BaseViewModel/ConnectorViewModel.cs
@@ -6,6 +6,7 @@ using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
+using AIStudio.Wpf.DiagramDesigner.Controls;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Helpers;
using SvgPathProperties;
@@ -255,6 +256,23 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
+
+ private LineAnimation _lineAnimation = LineAnimation.PathAnimation;
+ [Browsable(true)]
+ [CanDo]
+ [StyleName("LineAnimationStyle")]
+ public LineAnimation LineAnimation
+ {
+ get
+ {
+ return _lineAnimation;
+ }
+ set
+ {
+ SetProperty(ref _lineAnimation, value);
+ }
+ }
+
public virtual Dictionary PropertiesSetting
{
get