【问题标题】:Avoid translation when scaling polynom and center to mouse position将多项式和中心缩放到鼠标位置时避免平移
【发布时间】:2014-02-12 11:30:53
【问题描述】:

在我的应用程序中,我在画布中有一个多边形(4 个点 = 矩形)。我想通过使用鼠标滚轮将多边形缩放一个因子。为此,我使用以下代码:

    double scale = 1.0, factor = 1.01, cX, cY;

    void polygon_MouseWheel(object sender, MouseWheelEventArgs e)
    {
        cX = e.GetPosition(polygon).X;
        cY = e.GetPosition(polygon).Y;

        if (e.Delta > 0) scale *= factor;
        else scale /= factor;

        polygon.RenderTransform = new ScaleTransform(scale, scale, cX, cY);
    }

当我将鼠标指针放在多边形中的点 P(假设 P 是靠近多边形左上角的点)并向上或向下滚动时,这很好用。所以多边形根据那个点放大或缩小。但是当我将鼠标指针移动到另一个点 Q(靠近右下角)并继续放大或缩小时,多边形会向左上角移动一个量 s。看起来s的数量取决于P和Q之间的距离。所以如果P和Q之间的距离很大,那么偏移就很大。

在这种情况下,期望的行为是,多边形不会移动,而只是缩放到新的点 Q。

有没有人知道,转变的原因是什么?我很感谢任何提示。

示例代码:

<window ...>
    <Grid>
        <Canvas Name="canvas1" Background="LightBlue">
        <Polygon Points="100,100 100,300 300,300 300,100" Name="polygon" Fill="Black" MouseWheel="polygon_MouseWheel"/>
    </Canvas>
    </Grid>
</Window>
public MainWindow()
{
    InitializeComponent();
}

double scale = 1.0, factor = 1.01, cX, cY;

void polygon_MouseWheel(object sender, MouseWheelEventArgs e)
{
    cX = e.GetPosition(polygon).X;
    cY = e.GetPosition(polygon).Y;

    if (e.Delta > 0) scale *= factor;
    else scale /= factor;

    polygon.RenderTransform = new ScaleTransform(scale, scale, cX, cY);
}

【问题讨论】:

    标签: translation center polygon scaletransform


    【解决方案1】:

    好的,经过一段时间的尝试,我发现了导致这种行为的原因。 MSDN article of the UIElement.RenderTransform 属性表示:

    渲染转换不会重新生成布局大小或渲染大小信息。渲染变换通常用于为元素设置动画或应用临时效果。例如,元素可能在聚焦或鼠标悬停时缩放,或者在加载时可能会抖动以将注意力吸引到用户界面 (UI) 的该部分。

    这意味着,多边形本身,分别是多边形的点,不会被转换。应用 ScaleTransform 时,多边形的点不会改变,并且会保持在 xaml 中设置的状态。尽管如此,转换后的多边形会对鼠标事件做出反应,但鼠标位置会映射到原始边界。

    示例:让我们采用上面在 xaml 中定义的多边形并将其缩放 1.5 倍。多边形按比例显示,现在它的点似乎具有值 (150,150 150,450 450,450 450,150)。但在内部它仍然具有旧值(100,100 100,300 300,300 300,100)。如果您在缩放的右上角捕捉到鼠标指针的位置,它将是 (300,100) 而不是 (450,150)。

    使用鼠标位置作为缩放中心会导致缩放后的多边形发生偏移。

    解决方案是缩放多边形本身的点,而不是使用 ScaleTransform:

    void Scale(double factor, double centerX, double centerY)
    {
        PointCollection pc = new PointCollection();
    
        foreach (Point p in polygon.Points)
        {
            Point q = new Point();
    
            q.X = p.X;
            q.Y = p.Y;
    
            q.X -= centerX;    // translate
            q.Y -= centerY;
    
            q.X *= factor;     // scale
            q.Y *= factor;
    
            q.X += centerX;    // translate back
            q.Y += centerY;
    
            pc.Add(q);
        }
    
        polygon.Points = pc;   // polygon is defined in xaml
    }
    

    我不确定这是否是正确的方法,但它对我有用。

    【讨论】:

      猜你喜欢
      • 2013-12-19
      • 2014-04-16
      • 2011-09-28
      • 2023-02-11
      • 1970-01-01
      • 2022-01-21
      • 2020-05-28
      • 1970-01-01
      • 2018-03-07
      相关资源
      最近更新 更多