引入 縮放比例因子 double zoom = 1.0,繪圖時所有座標乘以此因子。
public partial class FunctionPlotter : Form {
double zoom = 1.0; // 1.0 = 原始大小
const double ZOOM_STEP = 1.2;
// 鼠標滾輪縮放
protected override void OnMouseWheel(MouseEventArgs e) {
if (e.Delta > 0) zoom *= ZOOM_STEP;
else zoom /= ZOOM_STEP;
zoom = Math.Clamp(zoom, 0.1, 10.0);
Invalidate(); // 觸發重繪
}
// 繪圖邏輯
protected override void OnPaint(PaintEventArgs e) {
var g = e.Graphics;
g.ScaleTransform((float)zoom, (float)zoom); // 整體縮放
// 繪製座標軸 (邏輯座標不變)
DrawAxes(g);
DrawFunction(g);
}
void DrawAxes(Graphics g) {
// 邏輯座標:X: -10..10, Y: -5..5
g.DrawLine(Pens.Gray, -10, 0, 10, 0); // X軸
g.DrawLine(Pens.Gray, 0, -5, 0, 5); // Y軸
// 刻度標籤同樣受縮放影響,自動放大
}
}
PointF pan = new PointF(0, 0); // 邏輯原點偏移
protected override void OnMouseDown(MouseEventArgs e) {
if (e.Button == MouseButtons.Middle) {
lastPan = e.Location;
isPanning = true;
}
}
protected override void OnMouseMove(MouseEventArgs e) {
if (isPanning) {
pan.X += (e.X - lastPan.X) / zoom;
pan.Y += (e.Y - lastPan.Y) / zoom;
lastPan = e.Location;
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e) {
var g = e.Graphics;
g.TranslateTransform(pan.X, pan.Y); // 先平移
g.ScaleTransform((float)zoom, (float)zoom); // 再縮放
DrawAxes(g);
DrawFunction(g);
}
zoom 動態計算刻度步長:double step = NiceStep(10 / zoom)。visibleRange = g.VisibleClipBounds 反變換到邏輯座標。