根据当前鼠标位置缩放图形 [英] Zooming graphics based on current mouse position
问题描述
我正在尝试根据鼠标的当前位置缩放绘图.现在我的 onMouseWheel 方法看起来像这样(基于
[edit1] 看起来您的 gfx 对象使用转发矩阵
这意味着转换的顺序颠倒了,所以方程会发生一些变化......这是您在 C++ 中的案例示例:
void scr2obj(double &ox,double &oy,double sx,double sy){//ox=(sx-x0)/缩放;//oy=(sy-y0)/缩放;ox=(sx/缩放)-x0;oy=(sy/zoom)-y0;}//---------------------------------------------------------------------------void obj2scr(double &sx,double &sy,double ox,double oy){//sx=x0+(ox*zoom);//sy=y0+(oy*zoom);sx=(x0+ox)*缩放;sy=(y0+oy)*缩放;}//---------------------------------------------------------------------------void __fastcall TForm1::FormMouseWheelDown(TObject *Sender, TShiftState Shift,TPoint &MousePos, bool &Handled){双 mx0,my0;scr2obj(mx0,my0,mx,my);缩放/=1.25;//缩小obj2scr(mx0,my0,mx0,my0);//x0+=mx-mx0;//y0+=my-my0;x0+=(mx-mx0)/缩放;y0+=(my-my0)/缩放;_重绘=真;}//---------------------------------------------------------------------------void __fastcall TForm1::FormMouseWheelUp(TObject *Sender, TShiftState Shift, TPoint &MousePos, bool &Handled){双 mx0,my0;scr2obj(mx0,my0,mx,my);缩放*=1.25;//放大obj2scr(mx0,my0,mx0,my0);//x0+=mx-mx0;//y0+=my-my0;x0+=(mx-mx0)/缩放;y0+=(my-my0)/缩放;_重绘=真;}//---------------------------------------------------------------------------
I'm trying to zoom a drawing based on the current position of the mouse. Right now my onMouseWheel method looks like this (based on 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
, and _translateY
are member variables.
I'm scaling the graphics, translating it, and then drawing the lines like this:
protected override void OnPaint(PaintEventArgs e)
{
g.ScaleTransform(_scale, _scale);
g.TranslateTransform(_translateX, _translateY);
//draw lines here
}
This video shows what happens when I try to zoom in and the zoom out on a certain point. What am I doing wrong?
This is what the code looks like in a sample panel class for testing purposes:
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);
}
}
Too lazy to make the equations right (and most likely would made similar mistake as you... I do not know if it is just me but exactly this easy stuff I cant handle and drives me mad). Instead I am dealing with this kind of tasks as follows (it is much safer from mistakes):
create transform functions between screen and world coordinates
So your mouse position is in screen coordinates and rendered stuff is in world coordinates. As this is only 2D then it is easy. make function that converts between these two. Your world to screen transform (if I am not overlooking something) is this:
g.ScaleTransform(_scale, _scale); g.TranslateTransform(_translateX, _translateY);
so:
screen_x=(world_x*_scale)+_translateX; screen_y=(world_y*_scale)+_translateY;
So the reverse:
world_x=(screen_x-_translateX)/_scale; world_y=(screen_y-_translateY)/_scale;
change of zoom/scale
The idea is that after zoom/scale change the mouse position should stay the same in world coordinates as before. so remember world coordinates of mouse before change. Then compute from it the screen position after change and the difference put into translation.
Here simple C++ example:
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;
}
//---------------------------------------------------------------------------
the mx,my
is actual mouse position in screen coordinates, the x0,y0
is the translation and zoom
is the scale.
And here captured GIF animation of this:
[edit1] It looks like your gfx objects use transponed matrices
That means the order of transformations is reversed so the equations change a bit... Here your case example in C++:
void scr2obj(double &ox,double &oy,double sx,double sy)
{
// ox=(sx-x0)/zoom;
// oy=(sy-y0)/zoom;
ox=(sx/zoom)-x0;
oy=(sy/zoom)-y0;
}
//---------------------------------------------------------------------------
void obj2scr(double &sx,double &sy,double ox,double oy)
{
// sx=x0+(ox*zoom);
// sy=y0+(oy*zoom);
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;
x0+=(mx-mx0)/zoom;
y0+=(my-my0)/zoom;
_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;
x0+=(mx-mx0)/zoom;
y0+=(my-my0)/zoom;
_redraw=true;
}
//---------------------------------------------------------------------------
这篇关于根据当前鼠标位置缩放图形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!