Wpf 如何仅允许在循环路径中拖动?
拖动时是否可以限制拖动源仅在圆形路径的边界内移动?创建一个点圆,然后当鼠标移动(我们正在拖动)时,计算最近的点并捕捉到该点 CircularDrag.xamlWpf 如何仅允许在循环路径中拖动?,wpf,Wpf,拖动时是否可以限制拖动源仅在圆形路径的边界内移动?创建一个点圆,然后当鼠标移动(我们正在拖动)时,计算最近的点并捕捉到该点 CircularDrag.xaml CircularDrag.xaml.cs 使用系统; 使用System.Linq; 使用System.Collections.Generic; 使用System.Windows; 使用System.Windows.Controls; 使用System.Windows.Input; 名称空间拖动边界 { 公共部分类CircularDra
CircularDrag.xaml.cs
使用系统;
使用System.Linq;
使用System.Collections.Generic;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Input;
名称空间拖动边界
{
公共部分类CircularDrag:UserControl
{
列出允许的车轮标记位置;
布尔标记;
公共通告
{
初始化组件();
}
私有void UserControl_SizeChanged(对象发送方,sizechangedventargs e)
{
var center=新点(e.NewSize.Width/2,e.NewSize.Height/2);
变量半径=(中心X
您不需要360点路径。相反,在拖动时,请使用Math.Atan2(Y,X)
计算当前角度,然后在圆上生成点。您仍然需要在调整和存储它们时计算中心
和半径
,或者在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);
}
我不能用这种方法将标记拖成一整圈(只有四分之一)。我遗漏了什么吗?我想我忘了计算相对于中心点的角度。以上更新。
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;
}
}
}
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);
}