缩放有三种典型类型:
- 放大到中心,由缩放按钮触发
- 放大鼠标位置,通过单击或滚轮触发
- 通过绘制矩形来放大矩形
我假设典型的设置:APictureBox
set to SizeMode=Zoom
nested in a Panel
with AutoScroll=true
和缩放,注意保持纵横比 of Image
and PictureBox
equal.
我们首先介绍一下术语:
- 有一个
Image
我们称之为bitmap and
- 它由一个显示
PictureBox
;我们就这样称呼它吧canvas..
- ..嵌套在
Panel
我们称之为frame
用户友好的缩放需要一个固定点,这是一个应该保持不变的点。
对于1)它是中心frame,对于 2) 它是鼠标位置,对于 3) 它是矩形的中心。
在缩放之前我们计算旧的变焦比,中的固定点frame, 中的不动点canvas最后是固定点bitmap.
缩放后我们计算新的变焦比和新的固定点canvas。最后我们用它来移动canvas带来固定的画布点到固定的框架点.
这是一个例子放大(当前)中心;这是两个按钮的常见点击事件,它只会使缩放比例加倍和减半。
当然,更细粒度的因素很容易实现;更好的是固定的缩放级别列表,就像 Photoshop 一样!
private void zoom_Click(object sender, EventArgs e)
{
PictureBox canvas = pictureBox1;
Panel frame = panel1;
// Set new zoom level, depending on the button
float zoom = sender == btn_ZoomIn ? 2f : 0.5f;
// calculate old ratio:
float ratio = 1f * canvas.ClientSize.Width / canvas.Image.Width;
// calculate frame fixed pixel:
Point fFix = new Point( frame.Width / 2, frame.Height / 2);
// calculate the canvas fixed pixel:
Point cFix = new Point(-canvas.Left + fFix.X, -canvas.Top + fFix.Y );
// calculate the bitmap fixed pixel:
Point iFix = new Point((int)(cFix.X / ratio),(int)( cFix.Y / ratio));
// do the zoom
canvas.Size = new Size( (int)(canvas.Width * zoom), (int)(canvas.Height * zoom) );
// calculate new ratio:
float ratio2 = 1f * canvas.ClientSize.Width / canvas.Image.Width;
// calculate the new canvas fixed pixel:
Point cFix2 = new Point((int)(iFix.X * ratio2),(int)( iFix.Y * ratio2));
// move the canvas:
canvas.Location = new Point(-cFix2.X + fFix.X, -cFix2.Y + fFix.Y);
}
Note虽然人们可以尝试挽回亲人AutoScrollValues
这不仅很难,因为它们的值有点奇怪,而且它也无法适应其他缩放类型。