我正在做一个Wpf应用程序,我创建了一个眼睛形状的控件,我在画布中放置了一个椭圆(眼睛),我的目的是当鼠标光标进入画布时,椭圆跟随鼠标光标。
您对如何执行此任务有什么建议吗?
非常感谢您的关注。
Cheers
EDIT
我已经更新了 Xaml 中的代码:
<Window Height="480" Title="Window2" Width="640" x:Class="WpfApplication5.Window2"
x:Name="Window" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<Storyboard x:Key="OnLoaded1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ctrCircle"
Storyboard.TargetProperty="(UIElement.RenderTransform).( TransformGroup.Children)[3].(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<ExponentialEase EasingMode="EaseOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ctrCircle"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<ExponentialEase EasingMode="EaseOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Style TargetType="Ellipse">
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="1" ScaleY="1"/>
</Setter.Value>
</Setter>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
</Style>
</Window.Resources>
<Canvas MouseMove="mov" x:Name="LayoutRoot">
<Border ackground="Black" B="" Canvas.Left="178" Canvas.Top="103"
CornerRadius="250" Height="255.5" Width="290" x:Name="border_eye">
<Ellipse Fill="#FFFFC600" Height="12" HorizontalAlignment="Left"
Margin="0" RenderTransformOrigin="0.5,0.5" Stroke="{x:Null}"
VerticalAlignment="Center" Visibility="Visible" Width="12" x:Name="ctrCircle">
<Ellipse.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</Ellipse.RenderTransform>
</Ellipse>
</Border>
</Canvas>
</Window>
并在后面的代码中:
private void mov(object sender, MouseEventArgs e)
{
System.Windows.Point pt = e.GetPosition((Canvas)sender);
Storyboard invokeStoryboard = this.Resources["OnLoaded1"] as Storyboard;
((DoubleAnimationUsingKeyFrames)invokeStoryboard.Children[0]).KeyFrames[0].Value = pt.X;
((DoubleAnimationUsingKeyFrames)invokeStoryboard.Children[1]).KeyFrames[0].Value = pt.Y;
invokeStoryboard.Begin();
}
现在我的目的是,当我在画布区域(LayoutRoot)中移动鼠标时,椭圆(ctrCircle)仅在边框(border_eye)内移动,并且不克服“border_eye”的区域,这种效果类似于眼睛。
您有任何意见来完成此步骤吗?
非常感谢
祝你今天过得愉快。
Cheers
以下是如何使用 WPF 画布中的眼睛的示例接收框架 http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx。使用 Rx 而不是直接附加到鼠标移动事件,您可以缓冲事件并仅每 10 毫秒更新一次瞳孔位置,从而减少总体 CPU 负载。
The Xaml
<UserControl
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"
x:Class="namespace.EyeDemo"
x:Name="UserControl"
d:DesignWidth="640" d:DesignHeight="480">
<Canvas x:Name="LayoutRoot" Background="GreenYellow">
<Ellipse Fill="Black" Width="120" Height="70" Canvas.Left="90" Canvas.Top="115"/>
<Ellipse x:Name="Eye" Fill="Black" Width="100" Height="50" Canvas.Left="100" Canvas.Top="125"/>
<Ellipse x:Name="Pupil" Fill="Red" Height="20" Canvas.Left="139" Canvas.Top="138" Width="20"/>
</Canvas>
</UserControl>
以及后面的代码
/// <summary>
/// Interaction logic for EyeDemo.xaml
/// </summary>
public partial class EyeDemo : UserControl
{
public EyeDemo()
{
this.InitializeComponent();
double majorRadius = Eye.Width / 2d;
double minorRadius = Eye.Height / 2d;
Point center = new Point( Canvas.GetLeft( Eye ) + majorRadius, Canvas.GetTop( Eye ) + minorRadius );
// create event streams for mouse down/up/move using reflection
// to keep taking mouse move events and return the X, Y positions
var mouseMove = from evt in Observable.FromEvent<MouseEventArgs>( LayoutRoot, "PreviewMouseMove" )
select (Point?)evt.EventArgs.GetPosition( this );
// subscribe to the stream of position changes and modify the Canvas.Left and Canvas.Top
// use the bound by elipse function to restrain the pupil to with the eye.
mouseMove.BufferWithTime( TimeSpan.FromMilliseconds( 10 ) ).Select( p => BoundByElipse( majorRadius, minorRadius, center, p.LastOrDefault() ) )
.ObserveOnDispatcher().Subscribe( pos =>
{
if( pos.HasValue )
{
Canvas.SetLeft( Pupil, pos.Value.X - Pupil.Width / 2d );
Canvas.SetTop( Pupil, pos.Value.Y - Pupil.Height / 2d );
}
} );
}
private Point? BoundByElipse( double majorRadius, double minorRadius, Point center, Point? point )
{
if( point.HasValue )
{
// Formular for an elipse is x^2 / a^2 + y^2 / b^2 = 1
// where a = majorRadius and b = minorRadius
// Using this formular we can work out if the point is with in the elipse
// or find the boundry point closest to the point
// Find the location of the point relative to the center.
Point p = new Point( point.Value.X - center.X, point.Value.Y - center.Y );
double a = majorRadius;
double b = minorRadius;
double f = p.X * p.X / (a * a) + p.Y * p.Y / (b * b);
if( f <= 1 )
{
// the point is with in the elipse;
return point;
}
else
{
// the point is outside the elipse, therefore need to find the closest location on the boundry.
double xdirection = point.Value.X > center.X ? 1 : -1;
double ydirection = point.Value.X > center.X ? 1 : -1;
double r = p.X / p.Y;
double x = p.Y != 0 ? Math.Sqrt( r * r * a * a * b * b / (r * r * b * b + a * a) ) : a;
double y = r != 0 ? x / r : (point.Value.Y > center.Y ? -b : b);
return new Point( center.X + xdirection * x, center.Y + ydirection * y );
}
}
else
{
return null;
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)