一般電子海圖系統(tǒng)都是通過鼠標(biāo)滾輪來(lái)實(shí)現(xiàn)海圖縮放包晰,按住鼠標(biāo)移動(dòng)實(shí)現(xiàn)海圖平移齐邦,鼠標(biāo)任意移動(dòng)獲取相應(yīng)的地理位置赴穗。因此必須在EncViewer_Load
事件中憔四,給繪圖控件skiaView
綁定如下鼠標(biāo)事件:
skiaView.MouseWheel += skiaView_MouseWheel;
skiaView.MouseDown += skiaView_MouseDown;
skiaView.MouseMove += skiaView_MouseMove;
skiaView.MouseUp += skiaView_MouseUp;
實(shí)現(xiàn)海圖平移
通常情況下膀息,海圖平移流程如下:
- 用戶左鍵按下鼠標(biāo)時(shí),記錄當(dāng)前鼠標(biāo)位置(x1, y1)了赵、海圖平移量1潜支,并標(biāo)識(shí)開始移動(dòng)
isDragging = true
; - 用戶按住鼠標(biāo)移動(dòng)時(shí)柿汛,動(dòng)態(tài)獲取鼠標(biāo)位置(x2, y2)冗酿,得到鼠標(biāo)平移量。
- 海圖平移量1加上鼠標(biāo)平移量络断,得出新的海圖平移量裁替,利用新海圖平移量,重新繪制海圖貌笨;
- 用戶松開鼠標(biāo)時(shí)弱判,標(biāo)識(shí)平移結(jié)束
isDragging = false
。
上述流程中的第2步躁绸,鼠標(biāo)每移動(dòng)一點(diǎn)裕循,海圖都重新繪制,而海圖繪制過程十分消耗資源净刮。因此剥哑,優(yōu)化上述流程如下:
- 用戶左鍵按下鼠標(biāo)時(shí),記錄當(dāng)前鼠標(biāo)位置(x1, y1)淹父、海圖平移量1株婴,并標(biāo)識(shí)開始移動(dòng)
isDragging = true
,獲取當(dāng)前視窗的截圖暑认; - 用戶按住鼠標(biāo)移動(dòng)時(shí)困介,動(dòng)態(tài)獲取鼠標(biāo)位置(x2, y2),得到鼠標(biāo)平移量蘸际。
- 利用鼠標(biāo)平移量座哩,將截圖繪制到視窗中;平移開始后粮彤,不再繪制海圖根穷;
- 用戶松開鼠標(biāo)時(shí),標(biāo)識(shí)平移結(jié)束
isDragging = false
导坟,海圖平移量1加上鼠標(biāo)平移量屿良,得出新的海圖平移量,利用新海圖平移量惫周,重新繪制海圖尘惧。
上述流程的平移過程中,海圖只在松開鼠標(biāo)時(shí)繪制一次递递,移動(dòng)過程只是繪制截圖喷橙。為實(shí)現(xiàn)上述流程啥么,需要對(duì)代碼進(jìn)行如下修改:
- 窗體中新增如下字段:
//鼠標(biāo)平移相關(guān) private bool isDragging = false; //平移開始標(biāo)志 private int preMousePosX = 0; //鼠標(biāo)按下時(shí)的位置 private int preMousePosY = 0; private int screenOffsetX = 0; //截圖的平移量 private int screenOffsetY = 0; private SKImage screenImage; //鼠標(biāo)按下時(shí)的截圖
- 按下鼠標(biāo)后,記錄鼠標(biāo)位置重慢,但由于無(wú)法在
skiaView_PaintSurface
獲取截圖饥臂,因此采用變通方法將截圖清空:private void skiaView_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { //開始平移,并記錄鼠標(biāo)位置 this.Cursor = Cursors.Hand; isDragging = true; preMousePosX = e.X; preMousePosY = e.Y; //此處無(wú)法直接獲取截圖似踱,因此設(shè)為空 screenImage = null; } }
- 移動(dòng)鼠標(biāo)中,記錄截圖平移量稽煤。
private void skiaView_MouseMove(object sender, MouseEventArgs e) { if (isDragging) { //按住鼠標(biāo)移動(dòng)核芽,記錄截圖平移量 screenOffsetX = e.X - preMousePosX; screenOffsetY = e.Y - preMousePosY; //只是移動(dòng)截圖 this.skiaView.Refresh(); } }
- 鼠標(biāo)松開后,結(jié)束平移酵熙,重繪海圖轧简。
private void skiaView_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (isDragging) { this.Cursor = Cursors.Default; isDragging = false; current_Dx += (e.X - preMousePosX); current_Dy -= (e.Y - preMousePosY); //重繪海圖 this.skiaView.Refresh(); } } }
- 最后,調(diào)整
skiaView_PaintSurface
的代碼匾二。當(dāng)處于平移狀態(tài)時(shí)哮独,動(dòng)態(tài)繪制截圖。private void skiaView_PaintSurface(object sender, SKPaintSurfaceEventArgs e) { //畫布 var canvas = e.Surface.Canvas; if (isDragging) //平移中 { if (screenImage == null) { screenImage = e.Surface.Snapshot(); } ClearCanvas(canvas); canvas.DrawImage(screenImage, screenOffsetX, screenOffsetY); } else { ClearCanvas(canvas); //繪制經(jīng)緯線及經(jīng)緯度 if (isDisplayGraticule) DrawGraticule(canvas); } }
平移中察藐,只是繪制截圖皮璧,因此四周出現(xiàn)部分空白區(qū)域;松開鼠標(biāo)分飞,重繪海圖悴务,空白區(qū)域消失。效果圖如下:
實(shí)現(xiàn)海圖縮放
縮放的中心點(diǎn)為屏幕中心(即滾動(dòng)過程中譬猫,屏幕中心位置不變讯檐,也可用別的邏輯,如鼠標(biāo)中心為縮放中心等)染服,因此在滾輪滾動(dòng)之前别洪,記錄當(dāng)前視窗中心地理坐標(biāo)。滾輪每滾動(dòng)一次縮放1.5倍(數(shù)值可調(diào)整)柳刮,得到新的海圖比例尺挖垛。利用中心地理坐標(biāo)、新比例尺诚亚、視窗大小晕换,計(jì)算出新的海圖平移量,最后重繪海圖站宗。
private void skiaView_MouseWheel(object sender, MouseEventArgs e)
{
if (e.Delta == 0) return;
var factor = e.Delta > 0 ? 0.6666666667d : 1.5d;
var newScale = (uint)(current_Scale * factor);
if ((factor > 1 && newScale > maxScale) || (factor < 1 && newScale < minScale)) return;
//原比例尺下中心位置對(duì)應(yīng)的經(jīng)緯度
var pos = GeoTools.ScreenPointToGeoPosition(current_Width / 2, current_Height / 2, current_Scale, current_Dx, current_Dy);
current_Scale = newScale;
//重新計(jì)算位置偏移
current_Dx = GeoTools.GetOffsetX(pos.Longitude, current_Scale, current_Width);
current_Dy = GeoTools.GetOffsetY(pos.Latitude, current_Scale, current_Height);
scaleInfo.Text = $"比例尺 1:{current_Scale}";
this.skiaView.Refresh();
}
獲取鼠標(biāo)處的地理位置
- 在窗體狀態(tài)欄添加
ToolStripStatusLabel
闸准,命名為mouseInfo
,用于顯示鼠標(biāo)處位置信息梢灭。 - 修改
skiaView_MouseMove
代碼夷家,直接把屏幕坐標(biāo)轉(zhuǎn)成地理坐標(biāo):
var pos = GeoTools.ScreenPointToGeoPosition(e.X, e.Y, current_Scale, current_Dx, current_Dy);
mouseInfo.Text = $"屏幕坐標(biāo): {e.X} {e.Y} 地理坐標(biāo): {pos}";