Как разрешить перетаскивание только по кругу? - PullRequest
5 голосов
/ 22 октября 2010

Можно ли ограничить источник перетаскивания, чтобы при перемещении он перемещался только внутри границ кругового контура?

Ответы [ 2 ]

5 голосов
/ 22 октября 2010

Вам не нужен путь из 360 точек.Вместо этого при перетаскивании вычислите текущий угол, используя Math.Atan2(Y,X), а затем сгенерируйте точку на окружности.Вам все равно придется вычислять center и radius при изменении размера и сохранять их или вычислять их внутри 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 голос
/ 22 октября 2010

Создайте круг точек, а затем, когда мышь перемещается (и мы перетаскиваем), вычисляем ближайшую точку и привязываемся к этой точке.

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;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...