虚线流动完成

This commit is contained in:
艾竹
2023-01-23 22:05:51 +08:00
parent c4f8a40b5c
commit 2b4662ed37
7 changed files with 296 additions and 36 deletions

View File

@@ -514,7 +514,11 @@
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Grid x:Name="selectedGrid">
<Grid.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding EditCommand}" CommandParameter="{Binding }" />
</Grid.InputBindings>
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header="删除" Command="{Binding DeleteConnectionCommand}" CommandParameter="{Binding}"/>
@@ -523,23 +527,21 @@
</ContextMenu>
</Grid.ContextMenu>
<Canvas Margin="0"
x:Name="selectedGrid"
HorizontalAlignment="Stretch"
<s:LineControl x:Name="line"/>
<Canvas HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Canvas.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding EditCommand}" CommandParameter="{Binding }" />
</Canvas.InputBindings>
<Path x:Name="poly" Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
<!--<Path x:Name="line" Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
StrokeThickness="{Binding ColorViewModel.LineWidth}"
StrokeDashArray="{Binding ColorViewModel.LineDashStyle,Converter={StaticResource LineDashConverter}}">
<Path.Data>
<MultiBinding Converter="{x:Static s:ConnectionPathConverter.Instance}">
<Binding Path="PathGeneratorResult"/>
<Binding Path="PathGeneratorResult"/>
</MultiBinding>
</Path.Data>
</Path>
<Path x:Name="rightarrow"
</Path>-->
<Path x:Name="rightarrow"
Data="{Binding ColorViewModel.RightArrowPathStyle,Converter={StaticResource ArrowPathConverter}}"
Visibility="{Binding Path=IsFullConnection, Converter={x:Static s:BoolToVisibilityConverter.Instance}}"
Fill="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
@@ -547,6 +549,8 @@
Width="{Binding ColorViewModel.RightArrowSizeStyle, Converter={StaticResource ArrowSizeConverter}}"
Stretch="Fill"
Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<TransformGroup>
@@ -554,24 +558,26 @@
<TranslateTransform X="{Binding EndPoint.X}" Y="{Binding EndPoint.Y}"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
<Path x:Name="leftarrow"
</Path>
<Path x:Name="leftarrow"
Data="{Binding ColorViewModel.LeftArrowPathStyle,Converter={StaticResource ArrowPathConverter}}"
Visibility="{Binding Path=IsFullConnection, Converter={x:Static s:BoolToVisibilityConverter.Instance}}"
Fill="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
HorizontalAlignment="Left"
Fill="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
Height="{Binding ColorViewModel.LeftArrowSizeStyle, Converter={StaticResource ArrowSizeConverter}}"
Width="{Binding ColorViewModel.LeftArrowSizeStyle, Converter={StaticResource ArrowSizeConverter}}"
Canvas.Left="{Binding StartPoint.X}"
Canvas.Top="{Binding StartPoint.Y}"
Stretch="Fill"
Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<RotateTransform x:Name="leftrot" Angle="{Binding StartAngle}"/>
<TransformGroup>
<RotateTransform x:Name="leftrot" Angle="{Binding StartAngle}"/>
<TranslateTransform X="{Binding StartPoint.X}" Y="{Binding StartPoint.Y}"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Canvas>
@@ -637,25 +643,12 @@
<DataTemplate.Triggers>
<DataTrigger Value="True"
Binding="{Binding IsSelected}">
<Setter TargetName="poly"
<!--<Setter TargetName="line"
Property="Stroke"
Value="Black" />
<Setter TargetName="rightarrow"
Property="Stroke"
Value="Black" />
<Setter TargetName="rightarrow"
Property="Fill"
Value="Black" />
<Setter TargetName="PART_VerticesContainer"
Property="Visibility"
Value="Visible"/>
</DataTrigger>
<DataTrigger Value="True"
Binding="{Binding IsSelected}">
<Setter TargetName="poly"
Property="Stroke"
Value="Black" />
Value="Black" />-->
<Setter TargetName="line"
Property="IsSelected"
Value="True" />
<Setter TargetName="rightarrow"
Property="Stroke"
Value="Black" />

View File

@@ -0,0 +1,37 @@
<UserControl x:Class="AIStudio.Wpf.DiagramDesigner.LineControl"
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"
xmlns:s="clr-namespace:AIStudio.Wpf.DiagramDesigner"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<s:ColorBrushConverter x:Key="ColorBrushConverter" />
<s:LineDashConverter x:Key="LineDashConverter"/>
</UserControl.Resources>
<Grid>
<Canvas x:Name="rootCanvas">
<Path x:Name="line" Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}"
StrokeThickness="{Binding ColorViewModel.LineWidth}"
StrokeDashArray="{Binding ColorViewModel.LineDashStyle,Converter={StaticResource LineDashConverter}}">
<Path.Data>
<MultiBinding Converter="{x:Static s:ConnectionPathConverter.Instance}">
<Binding Path="PathGeneratorResult"/>
</MultiBinding>
</Path.Data>
</Path>
<!--<Path x:Name="ball" Width="5" Height="5" Stretch="Fill" Fill="#eee">
<Path.Data>
<EllipseGeometry Center="100,100"
RadiusX="100"
RadiusY="100">
</EllipseGeometry>
</Path.Data>
</Path>-->
<Ellipse x:Name="ball" Fill="Red" Width="5" Height="5" Panel.ZIndex="1" />
</Canvas>
</Grid>
</UserControl>

View File

@@ -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
{
/// <summary>
/// LineControl.xaml 的交互逻辑
/// </summary>
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);
}
}
}

View File

@@ -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"));