2010-10-22 80 views

回答

5

你并不需要360点路径。相反,在拖动时,使用Math.Atan2(Y,X)计算当前角度,然后在圆上生成点。您仍然需要计算centerradius的大小并存储它们,或者在MouseMove中计算它们。

private void UserControl_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (!isDraggingMarker) 
      return; 
     var position = e.GetPosition(this); 

     double angle = Math.Atan2(position.Y - center.Y, position.X - center.X); 
     var closest = new Point(center.X + radius*Math.Cos(angle), 
           center.Y + radius*Math.Sin(angle)); 

     SetMarkerPosition(closest); 
    } 
+1

我不能用这种方法在一个完整的圆圈(只有四分之一)拖动标记。我错过了什么吗? – loraderon 2010-11-01 14:07:43

+1

我想我忘了计算相对于中心点的角度。上面更新。 – Justin 2010-11-03 19:02:09

+0

谢谢,它现在按预期工作! – loraderon 2010-11-04 07:28:30

1

创建一个点的圆,然后当鼠标移动(我们正在拖动)计算最近点并捕捉到该点。

CircularDrag.xaml

<UserControl x:Class="DraggingBoundaries.CircularDrag" 
     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" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300" 
     SizeChanged="UserControl_SizeChanged" 
     MouseMove="UserControl_MouseMove" 
     MouseLeave="UserControl_MouseLeave" 
     MouseLeftButtonUp="UserControl_MouseLeftButtonUp" 
     > 
    <Grid Background="White"> 
     <Border 
      x:Name="Marker" 
      HorizontalAlignment="Left" 
      VerticalAlignment="Top" 
      Width="14" 
      Height="14" 
      Background="CornflowerBlue" 
      CornerRadius="2" 
      BorderThickness="1" 
      BorderBrush="DarkGray" 
      MouseLeftButtonDown="Marker_MouseLeftButtonDown" 
      /> 
    </Grid> 
</UserControl> 

CircularDrag.xaml.cs

using System; 
using System.Linq; 
using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Input; 

namespace DraggingBoundaries 
{ 
    public partial class CircularDrag : UserControl 
    { 
     List<Point> allowedWheelMarkerPositions; 
     bool isDraggingMarker; 

     public CircularDrag() 
     { 
      InitializeComponent(); 
     } 

     private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e) 
     { 
      var center = new Point(e.NewSize.Width/2, e.NewSize.Height/2); 

      var radius = (center.X < center.Y ? center.X : center.Y) - 15; 

      allowedWheelMarkerPositions = CreateCirclePath(center, radius); 
      SetMarkerPosition(allowedWheelMarkerPositions.First()); 
     } 

     private List<Point> CreateCirclePath(Point center, double radius) 
     { 
      var result = new List<Point>(); 
      for (double angle = 0; angle <= 360; angle++) 
      { 
       double angleR = angle * (Math.PI/180); 
       double x = center.X + Math.Cos(angleR) * radius; 
       double y = center.Y - Math.Sin(angleR) * radius; 

       result.Add(new Point(x, y)); 
      } 
      return result; 
     } 

     private void UserControl_MouseMove(object sender, MouseEventArgs e) 
     { 
      if (!isDraggingMarker) 
       return; 
      var position = e.GetPosition(this); 

      var closest = allowedWheelMarkerPositions 
       .OrderBy(p => GetDistance(position, p)) 
       .First(); 

      SetMarkerPosition(closest); 
     } 

     private void SetMarkerPosition(Point closest) 
     { 
      Marker.Margin = new Thickness(closest.X - Marker.Width/2, closest.Y - Marker.Height/2, 0, 0); 
     } 

     private double GetDistance(Point a, Point b) 
     { 
      var deltaX = a.X - b.X; 
      var deltaY = a.Y - b.Y; 

      return Math.Sqrt(Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2)); 
     } 

     private void Marker_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
     { 
      isDraggingMarker = true; 
     } 

     private void UserControl_MouseLeave(object sender, MouseEventArgs e) 
     { 
      isDraggingMarker = false; 
     } 

     private void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
     { 
      isDraggingMarker = false; 
     } 
    } 
}