js - canvas事件检测

【背景】canvas事件检测是一个很常见的问题,目前常用的有几种:

  1. 用isPointInStroke 或isPointInPath检测
  2. 用点击位置与各要素线的距离来进行运算,对面等要素来说比较困难
  3. open layers 2.*版本中涉及到一个很精巧的办法,要素ID转化为color,通过点击事件取color,反求要素ID

针对第3种情况,进行一些说明。代码来自lib/render/canvas

关键属性和方法:

  • hitDetection : feature碰撞检测; 用于解决extranelGraphics绘制与获取.

  • hitOverflow : 存储碰撞溢出值, 用于分辨两个不同的要素, 最多16777215; 如果两个要素id相差超过这个值将不能够被正确检测;因为从颜色反取的ID

  • featureIdToHex : 将feature.id转换成RGB Hex值;

  • setHitContextStyle : 利用featureIdToHex将featureId转换成rgb颜色值, 然后根据图形形状在hitContext绘制对应颜色的要素;这样, 就实现了通过hit方式方向查询到featureId的解决方案; 最终都在getFeatureIdFromEvent方法里得到体现;

  • getFeatureIdFromEvent : 只有在hitDetection开启时返回feature, 否则返回

    var data = this.hitContext.getImageData(x, y, 1, 1).data; -> 获取RGB像素值;

    然后将RGB像素值转换成Hex值;

    Hex值再经过处理, id – 1 + this.hitOverflow 即是 featureId;

    Hex值FFFFFF : 16777215;

总结:核心思路是利用唯一ID及颜色的转换,来快速检索要素,思路很巧,

问题

如果要素相交,相交处检测是否有颜色偏差,还需测试确认

其他思路

  • mapv 利用重绘、isPointInStroke or isPointInPath来检测,检测效率略低,复杂度O(n)
  • zrender 每一个要素记录其mbr, 循环检测,首先检测点与mbr相交,然后用数学方法来检测是否在要素上 ,复杂度O(n)
  • 其他,可以结合Rtree, 对所有要素建立mbr索引,先快速检测,再精确检测,复杂度O(logn) ++

你可能感兴趣的:(js - canvas事件检测)