移动时可平移的图像抖动

时间:2019-05-22 15:32:59

标签: c# wpf

下面的类(PanImage)是此处Pan & Zoom Image的此线程的ZoomBorder类的改编。由于需要在图像上自定义绘画,因此无法使用边框。当用鼠标左键移动PanImage并仍然按下该按钮时,图像在两个位置之间来回跳跃。为什么这样做,如何解决此问题?

using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

class PanImage : Image
{

    public PanImage()
    {
        // add event-handler for changes of the SourceProperty of the Image class
        DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(Image.SourceProperty, typeof(Image));
        dpd?.AddValueChanged(this, delegate { Initialize(); });
    }


    private Point _origin;
    private Point _start;

    private TranslateTransform GetTranslateTransform()
    {
        return (TranslateTransform)((TransformGroup)RenderTransform)
          .Children.First(tr => tr is TranslateTransform);
    }

    private ScaleTransform GetScaleTransform()
    {
        return (ScaleTransform)((TransformGroup)RenderTransform)
          .Children.First(tr => tr is ScaleTransform);
    }

    public void Initialize()
    {
        RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.NearestNeighbor);
        TransformGroup group = new TransformGroup();
        ScaleTransform st = new ScaleTransform();
        TranslateTransform tt = new TranslateTransform();
        group.Children.Add(st);
        group.Children.Add(tt);

        RenderTransform = group;
        RenderTransformOrigin = new Point(0.0, 0.0);

        MouseLeftButtonDown += handle_MouseLeftButtonDown;
        MouseLeftButtonUp += handle_MouseLeftButtonUp;
        MouseMove += handle_MouseMove;
        PreviewMouseRightButtonDown += handle_PreviewMouseRightButtonDown;
    }

    public void Reset()
    {
        // reset zoom
        var st = GetScaleTransform();
        st.ScaleX = 1.0;
        st.ScaleY = 1.0;

        // reset pan
        var tt = GetTranslateTransform();
        tt.X = 0.0;
        tt.Y = 0.0;
    }


    private void handle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var tt = GetTranslateTransform();
        _start = e.GetPosition(this);
        _origin = new Point(tt.X, tt.Y);
        Cursor = Cursors.Hand;
        CaptureMouse();
    }

    private void handle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        ReleaseMouseCapture();
        Cursor = Cursors.Arrow;
    }

    void handle_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
    {
        Reset();
    }

    private void handle_MouseMove(object sender, MouseEventArgs e)
    {
        if (IsMouseCaptured)
        {
            Vector v = _start - e.GetPosition(this);
            var tt = GetTranslateTransform();
            tt.X = _origin.X - v.X;
            tt.Y = _origin.Y - v.Y;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

问题在于获取相对于要移动的元素的鼠标坐标。为了防止这种行为,请从父元素获取该职位:

private void handle_MouseMove(object sender, MouseEventArgs e) {
    ...
    UIElement parentElem = VisualTreeHelper.GetParent(this) as UIElement;
    Vector v = _start - e.GetPosition(parentElem);
    ...
}