使用拇指移动转换控件会产生奇怪的行为。

5
我在尝试使用拇指移动画布上的控件时遇到了奇怪的行为。当我将控件添加到画布并使用Thumb DragDelta事件来移动它时,一切看起来都很好。但是当我对控件应用旋转变换后,拖动它就变得很奇怪。控件开始围绕光标旋转,角度越大,圆圈就越大。
有人知道如何使拇指与变换后的元素配合工作吗?我已经花了一整天的时间尝试解决这个问题,但没有什么好的想法。
谢谢你的帮助!

这取决于您如何实现移动。 - H.B.
我正在使用e.HorizontalChange和e.VerticalChange,并将它们用于Canvas.SetTop()和Canvas.SetLeft()。这就是你所说的吗? - chiefanov
您还需要在哪个属性上应用旋转变换? - H.B.
我已经尝试了布局(Layout)和渲染变换(Render Transform),似乎两者都有相同的问题。 - chiefanov
4个回答

8
如果您对FrameworkElement应用任何旋转变换,这意味着与其关联的坐标网格已经旋转。 因此,该FrameworkElement的任何事件处理程序将接收到自己坐标网格中的位置值。
void DragThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
    //You can use this values when RotateTransform is null
    double deltaHorizontal = e.HorizontalChange;
    double deltaVertical = e.VerticalChange;

    //Transform coordinates
    Vector v = Math2DHelper.RotateVector2d(e.HorizontalChange, e.VerticalChange, Math2DHelper.D2R(rotationInDegrees));

    //Right values
    deltaHorizontal = v.X;
    deltaVertical = v.Y;

    ...
}

示例math2D辅助工具

public static class Math2DHelper
{
    public static Vector RotateVector2d(double x0, double y0, double rad)
    {
        Vector result = new Vector();
        result.X = x0 * Math.Cos(rad) - y0 * Math.Sin(rad);
        result.Y = x0 * Math.Sin(rad) + y0 * Math.Cos(rad);
        return result;
    }

    public static double D2R(double degree)
    {
        return (degree%360)*Math.PI/180;
    }
}

5
我遇到过这个问题并找到了解决方法,希望对他人有所帮助。在拖动滑块之前,您需要检查是否有任何转换。
private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
    {
        var thumb = dts as UIElement;
        var transform = thumb.RenderTransform as RotateTransform;
        Point dragDelta = new Point(e.HorizontalChange, e.VerticalChange);

            if (transform != null)
            {
                dragDelta = transform.Transform(dragDelta);
            }

            Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + dragDelta.X);
            Canvas.SetTop(thumb, Canvas.GetTop(thumb) + dragDelta.Y);

    }

1

如果你放弃Canvas属性,并按正确的顺序在TransformGroup中应用移动,它应该可以工作:

<Thumb.RenderTransform>
    <TransformGroup>
        <TranslateTransform x:Name="translation" />
        <RotateTransform ... />
    </TransformGroup>
</Thumb.RenderTransform>

translation.X += e.HorizontalChange;
translation.Y += e.VerticalChange;

如果你在组中切换顺序,你会得到与使用Canvas.Left/Top相同的行为。

(如果你对旋转进行了动画处理,这将无法帮助你)


这个更好了,但旋转现在是围绕画布的左上角而不是旋转项本身完成的。有什么建议可以解决这个问题吗? - chiefanov
那么你正在制作旋转动画? - H.B.
不,我在 DragDelta 事件结束时对旋转的项调用 InvalidateMeasure()。这会有影响吗? - chiefanov
可能是因为我只使用了上面的代码,所以它没有旋转。 - H.B.
我认为正在发生的是:我的原始项目位置是0,0。我使用平移变换将项目移动到50,50的位置。当应用旋转时,旋转以0,0为中心,作为其实际未经翻译的项目位置。 - chiefanov
1
我想我找到了一个适合我的解决方案。我不再使用e.HorizontalChange和e.VerticalChange,而是在拖动结束时使用画布中的鼠标位置来确定我的对象应该移动到哪里。虽然不是非常精确,但我认为它对于我想要实现的目标已经足够了。 - chiefanov

0

看起来当Thumb旋转时,HorizontalChange和VerticalChange不太兼容。因此,我只是使用画布中的光标位置获取左侧和顶部偏移量。虽然不完全准确,但对于我想要做的事情来说足够接近了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接