根据当前鼠标位置缩放图形

时间:2016-05-16 20:00:40

标签: c# winforms graphics zoom

我正在尝试根据鼠标的当前位置缩放绘图。现在我的onMouseWheel方法看起来像这样(基于this StackOverflow answer):

    private void onMouseWheel(object sender, MouseEventArgs e)
    {
        if (e.Delta > 0)
        {
            _scale *= 1.25f;
            _translateY = e.Y - 1.25f * (e.Y - _translateY);
            _translateX = e.X - 1.25f * (e.X - _translateX);
        }
        else
        {
            _scale /= 1.25f;
            _translateY = e.Y - 0.8f * (e.Y - _translateY);
            _translateX = e.X - 0.8f * (e.X - _translateX);
        }
        this.Invalidate();
    }

_scale_translateX_translateY是成员变量。

我正在缩放图形,翻译它,然后画出这样的线条:

    protected override void OnPaint(PaintEventArgs e)
    {
        g.ScaleTransform(_scale, _scale);
        g.TranslateTransform(_translateX, _translateY);
        //draw lines here
    }

This video显示当我尝试放大并缩小特定点时会发生什么。我做错了什么?

这是用于测试目的的示例面板类中的代码:

class Display : Panel
{
    public Display()
    {
        this.MouseWheel += new MouseEventHandler(this.onMouseWheel);
    }

    private void onMouseWheel(object sender, MouseEventArgs e)
    {
        if (e.Delta > 0)
        {
            _scale *= 1.25f;
            _translateY = e.Y - 1.25f * (e.Y - _translateY);
            _translateX = e.X - 1.25f * (e.X - _translateX);
        }
        else
        {
            _scale /= 1.25f;
            _translateY = e.Y - 0.8f * (e.Y - _translateY);
            _translateX = e.X - 0.8f * (e.X - _translateX);
        }
        this.Invalidate();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        g.ScaleTransform(_scale, _scale);
        g.TranslateTransform(_translateX, _translateY);

        Pen pen = new Pen(Color.Red);
        g.FillEllipse(pen.Brush, 50, 50, 10, 10);
    }
}

1 个答案:

答案 0 :(得分:1)

太懒了以使方程式正确(而且很可能会犯同样的错误......我不知道它是否仅仅是我,但正是这些简单的东西我无法处理并让我发疯)。相反,我正在处理以下这类任务(从错误中更加安全):

  1. 在屏幕和世界坐标之间创建转换函数

    因此,您的鼠标位置在屏幕坐标中,渲染的东西在世界坐标中。因为这只是 2D ,所以很容易。 make函数在这两者之间转换。你的世界屏幕变换(如果我不忽视某些东西)是这样的:

    /api/profiles?profileName=uniqueProfileName
    

    这样:

    g.ScaleTransform(_scale, _scale);
    g.TranslateTransform(_translateX, _translateY);
    

    反过来说:

    screen_x=(world_x*_scale)+_translateX;
    screen_y=(world_y*_scale)+_translateY;
    
  2. 更改缩放比例

    这个想法是在缩放/缩放后,鼠标位置应该保持与以前一样的世界坐标。所以记住改变之前鼠标的世界坐标。然后从中计算出更改后的屏幕位置以及转换后的差异。

  3. 这里是简单的C ++示例:

     
    world_x=(screen_x-_translateX)/_scale;
    world_y=(screen_y-_translateY)/_scale;
    

    double x0=0.0,y0=0.0,zoom=1.0,mx,my; //--------------------------------------------------------------------------- void scr2obj(double &ox,double &oy,double sx,double sy) { ox=(sx-x0)/zoom; oy=(sy-y0)/zoom; } //--------------------------------------------------------------------------- void obj2scr(double &sx,double &sy,double ox,double oy) { sx=x0+(ox*zoom); sy=y0+(oy*zoom); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormMouseWheelDown(TObject *Sender, TShiftState Shift,TPoint &MousePos, bool &Handled) { double mx0,my0; scr2obj(mx0,my0,mx,my); zoom/=1.25; // zoom out obj2scr(mx0,my0,mx0,my0); x0+=mx-mx0; y0+=my-my0; _redraw=true; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormMouseWheelUp(TObject *Sender, TShiftState Shift, TPoint &MousePos, bool &Handled) { double mx0,my0; scr2obj(mx0,my0,mx,my); zoom*=1.25; // zoom in obj2scr(mx0,my0,mx0,my0); x0+=mx-mx0; y0+=my-my0; _redraw=true; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift, int X,int Y) { mx=X; my=Y; } //--------------------------------------------------------------------------- 是屏幕坐标中的实际鼠标位置,mx,my是翻译,x0,y0是比例。

    此处捕获 GIF 动画:

    example

    [edit1]看起来您的gfx对象使用转发矩阵

    这意味着转换的顺序是相反的,所以方程式稍微改变了......在 C ++ 中的案例示例:

    zoom