【背景】canvas事件檢測是一個很常見的問題,目前常用的有幾種:
- 用isPointInStroke 或isPointInPath檢測
- 用點擊位置與各要素線的距離來進(jìn)行運算,對面等要素來說比較困難
- open layers 2.*版本中涉及到一個很精巧的辦法,要素ID轉(zhuǎn)化為color,通過點擊事件取color,反求要素ID
針對第3種情況,進(jìn)行一些說明。代碼來自lib/render/canvas
關(guān)鍵屬性和方法:
hitDetection : feature碰撞檢測; 用于解決extranelGraphics繪制與獲取.
hitOverflow : 存儲碰撞溢出值, 用于分辨兩個不同的要素, 最多16777215; 如果兩個要素id相差超過這個值將不能夠被正確檢測;因為從顏色反取的ID
featureIdToHex : 將feature.id轉(zhuǎn)換成RGB Hex值;
setHitContextStyle : 利用featureIdToHex將featureId轉(zhuǎn)換成rgb顏色值, 然后根據(jù)圖形形狀在hitContext繪制對應(yīng)顏色的要素;這樣, 就實現(xiàn)了通過hit方式方向查詢到featureId的解決方案; 最終都在getFeatureIdFromEvent方法里得到體現(xiàn);
-
getFeatureIdFromEvent : 只有在hitDetection開啟時返回feature, 否則返回
var data = this.hitContext.getImageData(x, y, 1, 1).data; -> 獲取RGB像素值;
然后將RGB像素值轉(zhuǎn)換成Hex值;
Hex值再經(jīng)過處理, id – 1 + this.hitOverflow 即是 featureId;
Hex值FFFFFF : 16777215;
總結(jié):核心思路是利用唯一ID及顏色的轉(zhuǎn)換,來快速檢索要素,思路很巧,
問題
如果要素相交,相交處檢測是否有顏色偏差,還需測試確認(rèn)
其他思路
- mapv 利用重繪、isPointInStroke or isPointInPath來檢測,檢測效率略低,復(fù)雜度O(n)
- zrender 每一個要素記錄其mbr, 循環(huán)檢測,首先檢測點與mbr相交,然后用數(shù)學(xué)方法來檢測是否在要素上 ,復(fù)雜度O(n)
- 其他,可以結(jié)合Rtree, 對所有要素建立mbr索引,先快速檢測,再精確檢測,復(fù)雜度O(logn) ++