以下代码绘制一条线,围绕其左端旋转30度,将其恢复到原始位置,绕其右端旋转30度,然后重复几次。
如何在不将线恢复到原来位置的情况下对这些旋转进行排序?第一次旋转(左端点周围)导致右端点移动;所以我希望下一次轮换围绕它的新位置。
序列的净效应应该是使线段“向前走”。
(请注意,此代码反复使用相同的角度。但我需要一个解决方案,如果角度每次都不同,它也会起作用。)
XAML: -
<UserControl x:Class="Rotation.MainPage"
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"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
<Grid x:Name="LayoutRoot">
<Canvas Width="500" Height="500">
<Line Name="TheLine" X1="100" Y1="200" X2="200" Y2="200" Stroke="Black" StrokeThickness="5"></Line>
</Canvas>
</Grid>
</UserControl>
代码: -
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace Rotation
{
public partial class MainPage : UserControl
{
double x1, y1, x2, y2;
public MainPage()
{
InitializeComponent();
for (int i = 0; i < 5; i++)
{
_animations.Add(() => { return rot(true, -30); });
_animations.Add(() => { return rot(false, 30); });
}
_enumerator = _animations.GetEnumerator();
x1 = TheLine.X1;
x2 = TheLine.X2;
y1 = TheLine.Y1;
y2 = TheLine.Y2;
this.Loaded += delegate(object sender, RoutedEventArgs e)
{
RunNextAnimation();
};
}
List<Func<Storyboard>> _animations = new List<Func<Storyboard>>();
IEnumerator<Func<Storyboard>> _enumerator;
public void AnimationCompleted(object sender, EventArgs args)
{
RunNextAnimation();
}
void RunNextAnimation()
{
if (_enumerator.MoveNext())
{
Func<Storyboard> fn = _enumerator.Current;
if (fn != null)
{
Storyboard board = fn();
board.Completed += AnimationCompleted;
board.Begin();
}
}
}
public Storyboard rot(bool aroundLeft, double angle)
{
Storyboard board = new Storyboard();
int duration = 5;
if (true)
{
RotateTransform rot = new RotateTransform();
if (aroundLeft)
{
rot.CenterX = x1;
rot.CenterY = y1;
}
else
{
rot.CenterX = x2;
rot.CenterY = y2;
}
TheLine.RenderTransform = rot;
DoubleAnimation an = new DoubleAnimation();
an.Duration = new Duration(new TimeSpan(0, 0, duration));
an.From = 0;
an.To = angle;
board.Children.Add(an);
Storyboard.SetTarget(an, TheLine);
Storyboard.SetTargetProperty(an, new PropertyPath("(UIElement.RenderTransform).Angle"));
}
return board;
}
}
}
答案 0 :(得分:1)
我想出了一种方法:每次旋转,计算线的端点移动到的位置。然后在开始下一次旋转之前,移动直线,使其位置和角度反映所需旋转的中心。
这是执行此操作的代码。我现在使用的是包含复合形状的画布,而不是一条线,这是一个更通用的目的。
XAML:
<UserControl x:Class="Rotation.MainPage"
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"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
<Grid x:Name="LayoutRoot">
<Canvas Width="500" Height="500">
<Canvas Name="TheRect" Canvas.Left="100" Canvas.Top="100" Width="100" Height="20">
<Rectangle Canvas.Left="0" Canvas.Top="0" Width="100" Height="20" Stroke="Black" StrokeThickness="1"></Rectangle>
<Ellipse Width="10" Height="10" Fill="Blue" Canvas.Left="0" Canvas.Top="0" />
</Canvas>
</Canvas>
</Grid>
</UserControl>
C#:
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace Rotation
{
public partial class MainPage : UserControl
{
double x1, y1, x2, y2, w;
double lastAngle;
public MainPage()
{
InitializeComponent();
for (int i = 0; i < 10; i++)
{
_animations.Add(() => { return rot(true, 30); });
_animations.Add(() => { return rot(false, -30); });
}
_enumerator = _animations.GetEnumerator();
x1 = (double)TheRect.GetValue(Canvas.LeftProperty);
y1 = (double)TheRect.GetValue(Canvas.TopProperty);
w = (double)TheRect.GetValue(Canvas.WidthProperty);
x2 = x1 + w;
y2 = y1;
lastAngle = 0.0;
this.Loaded += delegate(object sender, RoutedEventArgs e)
{
RunNextAnimation();
};
}
List<Func<Storyboard>> _animations = new List<Func<Storyboard>>();
IEnumerator<Func<Storyboard>> _enumerator;
public void AnimationCompleted(object sender, EventArgs args)
{
RunNextAnimation();
}
void RunNextAnimation()
{
if (_enumerator.MoveNext())
{
Func<Storyboard> fn = _enumerator.Current;
if (fn != null)
{
Storyboard board = fn();
board.Completed += AnimationCompleted;
board.Begin();
}
}
}
public Storyboard rot(bool aroundLeft, double angle)
{
Storyboard board = new Storyboard();
int duration = 5;
if (true)
{
TheRect.SetValue(Canvas.LeftProperty, aroundLeft ? x1 : x1 - w*(1 - Math.Cos(lastAngle * Math.PI / 180)));
TheRect.SetValue(Canvas.TopProperty, aroundLeft ? y1 : y2);
RotateTransform rot = new RotateTransform();
rot.CenterX = aroundLeft ? 0 : w;
rot.CenterY = aroundLeft ? 0 : 0;
rot.Angle = aroundLeft ? lastAngle : -lastAngle;
TheRect.RenderTransform = rot;
DoubleAnimation an = new DoubleAnimation();
an.Duration = new Duration(new TimeSpan(0, 0, duration));
an.From = lastAngle;
an.To = lastAngle + angle;
board.Children.Add(an);
Storyboard.SetTarget(an, TheRect);
Storyboard.SetTargetProperty(an, new PropertyPath("(UIElement.RenderTransform).Angle"));
// and for next time around:
lastAngle += angle;
if (aroundLeft)
{
// rotating will move x2,y2; compute the updated values for next time
double x0 = x2 - x1;
double y0 = y2 - y1;
double sin = Math.Sin(angle * Math.PI / 180.0);
double cos = Math.Cos(angle * Math.PI / 180.0);
x2 = x1 + (x0 * cos) - (y0 * sin);
y2 = y1 + (x0 * sin) + (y0 * cos);
}
else
{
// rotating will move x1, y1; compute the updated values for next time
double x0 = x1 - x2;
double y0 = y1 - y2;
double sin = Math.Sin(angle * Math.PI / 180.0);
double cos = Math.Cos(angle * Math.PI / 180.0);
x1 = x2 + (x0 * cos) - (y0 * sin);
y1 = y2 + (x0 * sin) + (y0 * cos);
}
}
return board;
}
}
}