开发者

Object the follow the cursor of the mouse

i am doing a Wpf Application and i create a Control with the shape of an eye ,i put a Ellipse(eye) in a Canvas and my purpose is when the cursor of the mouse enter in the Canvas the Ellipse follow the cursor of mouse. Do you have an开发者_StackOverflowy suggestion how perform this task? Thanks so much for your attention.

Cheers

EDIT

I have update my code in 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>

and in the code behind :

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();
    }

now my purpose is when i move the mouse in the Canvas area(LayoutRoot) the Ellipse(ctrCircle) move only inside the Border(border_eye) and don't overcome the area of the "border_eye" this effect is similar an eye.

Do you have any input to work out this step?

Thanks so much

Have a nice day.

Cheers


Here is an example of how to do an eye in a WPF canvas using the Rx framework. Using Rx instead of attaching to the mouse move event directly allows you to buffer the events and only update the Pupil position every 10 milliseconds reducing the overall CPU load.

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>

and the code behind

/// <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;
        }
    }
}


Use MouseMove and make sure the Canvas has a Background for hit testing.

XAML:

<Canvas MouseMove="Canvas_MouseMove"
        Background="Transparent">
    <Ellipse x:Name="eye"
             Width="50"
             Height="20"
             Fill="Blue" />
</Canvas>

Codebehind:

private void Canvas_MouseMove( object sender, System.Windows.Input.MouseEventArgs e )
{
   var pos = e.GetPosition((Canvas)sender);
   Canvas.SetLeft(eye, pos.X);
   Canvas.SetTop(eye, pos.Y);
}


The way you did it is almost correct, except that you can not modify properties of an animation after the animation was used. You have to create a new animation using Clone() and modify it, remove the old animation and then apply the new modified one.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜