|Native地图与Web融合技术的应用与实践( 三 )


  1. 用户触摸动作首先被手势分发层捕获 , 手势分发层判断用户点击到热区数据范围内 , 将消息分发到WebView H5层处理 。
  2. WebView H5层收到消息 , 对消息进行处理(比如:在地图中添加一个终点Marker) , 通过通讯桥将消息传递到Native地图层 。
  3. Native地图层收到消息 , 并执行添加Marker操作 , 完成后返回成功信息 。 上述总体流程为:手势分发层-->1-->2-->3-->6-->7 。
手势消息分发给Native地图层流程
主要为上图5-->6-->7过程 , 如下:
  1. 手势分发层捕获到消息 , 发现用户手势与当前热区数据矩形没有交集 , 于是将获取的消息分发到Native地图层 。
  2. 如果消息是拖动操作 , 则Native地图自动识别拖动地图消息 , 实现移动地图的效果 , 涉及流程为:手势分发层-->5 。
  3. 如果消息是点击操作 , 比如我们想实现点击地图中的Marker , 将消息传递给H5处理的功能 。 实现步骤为我们事先在添加Marker时增加一个点击事件(Native地图层实现) , Marker被点击时Native地图层会派发此事件 , 事件消息会通过JSBridge技术从Native地图层传到H5层 , 最后H5层获取到点击消息 。 整个操作流程为:手势分发层-->5-->6-->7 。
热区数据的动态更新策略
因为打车业务底部的面板高度是可伸缩的 , 所以底部的热区数据并不是静止不动的 , 需要考虑热区数据也要随着DOM元素的拉伸做同步调整 。 可以通过在WebView H5层监控DOM的变化 , DOM元素发生变化时 , 获取变化后的DOM元素位置、大小 , 格式化为热区数据 , 并更新到消息分发热区数据部分 。 因为拉伸动作是一个连续的动画效果 , 为了高效 , 我们只在动画结束的那一刻更新热区数据 , 中间过渡期不做处理 。 此整体流程为:2-->3-->4 。
4. 点评App中的落地实践
4.1 手势分发层关键代码
这部分功能需要Native端同学实现 , 包括iOS与Android 。 两端分别在启动App时设置三层内容 , 最上层是手势触摸事件接收层 , 中间是WebView层(背景设置透明) , 最下层是Native地图层(如腾讯地图SDK) 。 用数组记录当前热区数据 , 当手势分发层有事件发生时 , 通过Touch事件获取手指位置信息 , 遍历热区数组判断手指位置是否与热区的矩形相交 , 如相交则将消息分发给WebView层 , 否则分发给Native层 。 下边是Android与iOS消息分发关键代码:
Android分发层关键代码
@Override public boolean dispatchTouchEvent(MotionEvent event){ if(event.getAction() == MotionEvent.ACTION_DOWN) { // 分发层接收到手势触摸消息 , 通过dispatchService类判断手势是否落在热区内 , 从而确定消息分发的对象 this.touchHandler = dispatchService.inRegion(event) ? TouchHandler.WebView : TouchHandler.MapView; } // 分发给Native地图层 if(this.touchHandler == TouchHandler.MapView) { return this.mapView.dispatchTouchEvent(event); } // 分发给WebView H5层 return super.dispatchTouchEvent(event); }iOS分发层关键代码
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitTestView = nil; // 分发层接收到手势触摸消息 , 通过pointInHotspot判断手势是否落在热区内 , 从而确定消息分发的对象 if ([self pointInHotspot:point]) { // 分发给WebView H5层 hitTestView = [self.WebView hitTest:point withEvent:event]; }else{ // 分发给Native地图层 hitTestView = [self.mapView hitTest:point withEvent:event]; } return hitTestView; }4.2 WebView H5层
该层有2个功能: