我如何只允许在圆形路径中拖动?

时间:2010-10-22 12:17:49

标签: wpf

是否可以将拖动源限制为仅在拖动时在圆形路径的边界内移动?

2 个答案:

答案 0 :(得分: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 :(得分: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;
        }
    }
}