WPF快照网格的实现

WPF快照网格的实现,wpf,xaml,Wpf,Xaml,我正在尝试使用WPF和画布实现一个快照网格。我认为我的数学是关闭的,因为UIElement不会捕捉到背景中的网格。下面是我用来创建网格的xaml,以及我用来尝试将UIElement捕捉到最近的网格线的方法。一旦触发鼠标按钮向上事件,将立即触发所使用的方法。如果这不是WPF的正确方法,有人能给我指出正确的方向吗 XAML Canvas.GetLeft(element)将返回一个double,因此即使gridWidth是一个整数,它将执行双精度算术,并且除法和乘法将或多或少地抵消。我想你想做以下一件

我正在尝试使用WPF和画布实现一个快照网格。我认为我的数学是关闭的,因为UIElement不会捕捉到背景中的网格。下面是我用来创建网格的xaml,以及我用来尝试将UIElement捕捉到最近的网格线的方法。一旦触发鼠标按钮向上事件,将立即触发所使用的方法。如果这不是WPF的正确方法,有人能给我指出正确的方向吗

XAML

Canvas.GetLeft(element)
将返回一个double,因此即使
gridWidth
是一个整数,它将执行双精度算术,并且除法和乘法将或多或少地抵消。我想你想做以下一件事:

double xSnap = Math.Floor(Canvas.GetLeft(element) / gridWidth) * gridWidth;
double xSnap = Math.Ceiling(Canvas.GetLeft(element) / gridWidth) * gridWidth;
double xSnap = Math.Round(Canvas.GetLeft(element) / gridWidth) * gridWidth;

这些函数将除法结果四舍五入为整数,并返回gridWidth的倍数

你的问题是你的函数实际上什么都不做。你除以网格大小,然后乘以网格大小,所以实际上你什么都没做(2*16/16=2)。您需要使用的是模数
%
操作符,并根据与网格大小的距离调整x/y位置

这是一个工作函数,如果更靠近左/顶轴网线,则捕捉左/顶轴网线,否则捕捉右/下轴网线:

private void SnapToGrid(UIElement){
double xSnap=Canvas.GetLeft(元素)%GRID\u SIZE;
double ySnap=Canvas.GetTop(元素)%网格大小;
//如果小于网格大小的一半,则向左/向上捕捉
//(减去余数),
//否则,将其向右/向下移动网格大小的剩余距离
//(通过将剩余距离添加到下一个栅格点)。

如果(xSnap的想法是确保任何对象的位置限制在某个数字集内;即,最终位置应四舍五入,并在该集合内

集合由任意数字的所有因素组成,
j
j
控制“捕捉”的强度,并确定出现在集合中的数字。新位置也必须只包含出现在集合中的数字

例如,假设对象的原始位置是
(5,0)
,我们希望将其移动到
(16,23)
。让我们继续拍摄5:这意味着对象的位置可能只包含5的因子。原始位置已落在此集中,但新位置不在其中

为了模拟“捕捉”,新位置必须落在
(15,20)
(20,25)
上。找到最接近的1623的因子将给出正确的点。在大多数情况下,有必要对结果进行四舍五入

示例

//Get original point of object relative to container element
var original_point = e.GetPosition(sender);

//Calculate new x and y position based on mouse
//var new_x = ...
//var new_y = ...

//New position must be multiple of 8    
var snap = 8;

//Get nearest factor of result position
new_x = original_point.X.NearestFactor(snap);
new_y = original_point.Y.NearestFactor(snap);

public static double NearestFactor(this double Value, double Factor)
{
    return Math.Round((Value / Factor), MidpointRounding.AwayFromZero) * Factor;
}
不用说,在调整对象大小时也可以使用此算法,以确保对象的位置和大小“捕捉”

double xSnap = Math.Floor(Canvas.GetLeft(element) / gridWidth) * gridWidth;
double xSnap = Math.Ceiling(Canvas.GetLeft(element) / gridWidth) * gridWidth;
double xSnap = Math.Round(Canvas.GetLeft(element) / gridWidth) * gridWidth;
//Get original point of object relative to container element
var original_point = e.GetPosition(sender);

//Calculate new x and y position based on mouse
//var new_x = ...
//var new_y = ...

//New position must be multiple of 8    
var snap = 8;

//Get nearest factor of result position
new_x = original_point.X.NearestFactor(snap);
new_y = original_point.Y.NearestFactor(snap);

public static double NearestFactor(this double Value, double Factor)
{
    return Math.Round((Value / Factor), MidpointRounding.AwayFromZero) * Factor;
}