我正在尝试根据鼠标的当前位置缩放绘图.现在我的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,_translateY); Pen pen = new Pen(Color.Red); g.FillEllipse(pen.Brush,50,10,10); } }
解决方法
懒得让方程式正确(而且很可能会犯同样的错误……我不知道它是否仅仅是我,但确切地说,这些简单的东西我无法处理并让我发疯).相反,我正在处理如下的这类任务(它从错误中更加安全):
>在屏幕和世界坐标之间创建变换功能
因此,您的鼠标位置在屏幕坐标中,渲染的东西在世界坐标中.因为这只是2D,所以很容易. make函数在这两者之间转换.你的世界屏幕转换(如果我不忽视某些东西)是这样的:
g.ScaleTransform(_scale,_scale); g.TranslateTransform(_translateX,_translateY);
所以:
screen_x=(world_x*_scale)+_translateX; screen_y=(world_y*_scale)+_translateY;
所以相反:
world_x=(screen_x-_translateX)/_scale; world_y=(screen_y-_translateY)/_scale;
>改变缩放/比例
我们的想法是,在缩放/缩放后,鼠标位置应保持与以前相同的世界坐标.所以记住改变之前鼠标的世界坐标.然后从中计算出更改后的屏幕位置和转换后的差异.
这里简单的C例子:
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,my); zoom/=1.25; // zoom out obj2scr(mx0,mx0,my0); x0+=mx-mx0; y0+=my-my0; _redraw=true; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormMouseWheelUp(TObject *Sender,my); zoom*=1.25; // zoom in obj2scr(mx0,my0); x0+=mx-mx0; y0+=my-my0; _redraw=true; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormMouseMove(TObject *Sender,int X,int Y) { mx=X; my=Y; } //---------------------------------------------------------------------------
mx,我是屏幕坐标中的实际鼠标位置,x0,y0是平移,缩放是比例.
这里捕获了GIF动画:
[edit1]看起来你的gfx对象使用转发矩阵
这意味着转换的顺序是相反的,所以方程式改变了一点……这里你的例子在C中:
void scr2obj(double &ox,double sy) { // ox=(sx-x0)/zoom; // oy=(sy-y0)/zoom; ox=(sx/zoom)-x0; oy=(sy/zoom)-y0; } //--------------------------------------------------------------------------- void obj2scr(double &sx,double oy) { // sx=x0+(ox*zoom); // sy=y0+(oy*zoom); sx=(x0+ox)*zoom; sy=(y0+oy)*zoom; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormMouseWheelDown(TObject *Sender,bool &Handled) { double mx0,my0; scr2obj(mx0,my); zoom/=1.25; // zoom out obj2scr(mx0,my0); // x0+=mx-mx0; // y0+=my-my0; x0+=(mx-mx0)/zoom; y0+=(my-my0)/zoom; _redraw=true; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormMouseWheelUp(TObject *Sender,my); zoom*=1.25; // zoom in obj2scr(mx0,my0); // x0+=mx-mx0; // y0+=my-my0; x0+=(mx-mx0)/zoom; y0+=(my-my0)/zoom; _redraw=true; } //---------------------------------------------------------------------------
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。