2010-11-04 51 views
5

Tôi đang làm một ứng dụng Wpf và tôi tạo một điều khiển với hình dạng của một mắt, tôi đặt một hình elip (mắt) trong Canvas và mục đích của tôi là khi con trỏ chuột nhập trong Canvas Ellipse theo con trỏ chuột. Bạn có đề xuất nào về cách thực hiện tác vụ này không? Cảm ơn bạn rất nhiều vì đã chú ý đến bạn.Đối tượng theo con trỏ chuột

Cheers

EDIT

Tôi có cập nhật mã của tôi trong 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> 

và trong các mã sau:

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

tại mục đích của tôi là khi tôi di chuyển chuột trong vùng Canvas (LayoutRoot), Ellipse (ctrCircle) chỉ di chuyển bên trong Border (border_eye) và không vượt qua khu vực của "border_eye" hiệu ứng này tương tự như một con mắt.

Bạn có bất kỳ đầu vào nào để thực hiện bước này không?

Cảm ơn rất nhiều

Chúc một ngày tốt đẹp.

Chúc mừng

Trả lời

7

Dưới đây là ví dụ về cách thực hiện một con mắt trong canvas WPF bằng cách sử dụng Rx framework. Sử dụng Rx thay vì gắn vào sự kiện di chuyển chuột trực tiếp cho phép bạn đệm các sự kiện và chỉ cập nhật vị trí học sinh sau mỗi 10 mili giây làm giảm tải CPU tổng thể.

Các 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> 

và mã đằng sau

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

Sử dụng MouseMove và đảm bảo Canvas có Nền để thử nghiệm lần truy cập.

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); 
} 
+0

Cảm ơn Chris tôi quên viết ra một cách chi tiết, mắt nghỉ trong một thành phần i viết xuống mã: ... vì vậy tôi muốn khi chuột nhập vào mainCanvas con mắt di chuyển bên trong canvas_eye mà không đi ra ngoài biên giới canvas_eye. Xin lỗi vì lời giải thích không tốt của tôi trước đây, hy vọng bạn có được điểm của nhiệm vụ của tôi. – JayJay

+0

Có vẻ như JayJay cũng muốn một sự chậm trễ nới lỏng trong 8 giây, được định nghĩa trong XAML. – bitbonk

1

Cách bạn đã làm nó gần như là chính xác, ngoại trừ việc bạn không thể sửa đổi các thuộc tính của một hình ảnh động sau khi các hình ảnh động được sử dụng. Bạn phải tạo một hoạt ảnh mới bằng cách sử dụng Clone() và sửa đổi nó, xóa hoạt ảnh cũ và sau đó áp dụng hiệu ứng mới được sửa đổi.

Các vấn đề liên quan