给你的地图点灯

曾经坐在飞机上俯瞰整个北京城,在万米高空上可以看到北京的全貌,即使是凌晨一两点,北京依然灯火通明,俨然是一座不眠之城。四通八达的交通线仿佛是这座城市的血脉,里面流淌着的,是生活在这里的人们的梦想。

然而,今天要讲的不是北京,也不是梦想。今天要讲的是我们该如何在地图上点起一盏灯,就像夜幕下的北京城一样。

为了方便理解,我们先看一下最终的实现效果。


给你的地图点灯_第1张图片
最终效果.png

没错,就是要在夜幕下,放几盏灯,告诉别人这块区域目前有人正在里面工作。

在讲解如何实现这种效果前,先分享一下之前的那种存在问题的思路

之前的做法是:
  • 位于底部的阴影区域当做一个大的PolygonView,并且充满屏幕。
  • 位于上面的高亮区域当做另外的PolygonView,依次添加,并设置它们的背景色与透明度,模拟高亮。

然而这样做会产生一个无法避免的问题,那就是无论我们怎么设置高亮区域的背景色与透明度,都不够好看:透明度低的时候,就看不到下面的地图,透明度高的时候,虽然能看到下面的地图,但是却雾蒙蒙的,仿佛那片高亮区域,被雾霾笼罩了。。

给你的地图点灯_第2张图片
被雾霾笼罩的效果图.png

那么问题来了,如何让大晚上还在工作的人们,少呼吸点雾霾呢。

思路其实很简单,只需要换个角度来思考就可以了,那就是我们不再分别绘制高亮区域和底部的全屏阴影区域,而是只需要绘制一个阴影区域就可以了,这样剩下的没有绘制的区域自然就是没有雾霾的。
对,再说一遍,只需要绘制一个阴影区域就可以。
先来一张图:

给你的地图点灯_第3张图片
绘制过程分解.png

屏幕的四个点分别是S1、S2、S3、S4,两个高亮区域分别是区域A区域B,区域A的四个点分别是A1、A2、A3、A4,区域B的四个点分别是B1、B2、B3、B4。我们要绘制的就是除去区域A,区域B后,把剩下的那部分当做一个PolygonView来绘制。(注意:这里所说的点是指经纬度点,而不是point点)

So ,如何得到阴影区域的Polygon

  • 首先声明一个经纬度数组CLLocationCoordinate2D * coors,用来存放区域坐标点。
  • 先从S1点开始,将其加入到coors中,下一个点是A1点,然后依次添加A2、A3、A4
  • 添加完A4后,** 一定要再将A1点加一遍**,以构成一个闭环,而不是直接去添加区域B的点,此时A1点被添加了两遍。
  • 接着添加区域B的点,先是B1点,然后依次添加B2、B3、B4
  • 添加完B4后,像区域A一样,一定要再添加一遍B1点,以构成闭环。此时B1点被添加两遍。
  • 由于此时只有两个区域,所以添加完B1点后,我们需要返回,这里需要注意的一定要原路返回。所以需要再添加一遍A1点,此时A1点被添加了3遍(注意:非屏幕边界点最多被添加三遍)。
  • 接着我们需要再次添加S1点,也就是说从S1点,出去转了一圈后,最后必须回到S1点。此时S1点被添加2遍。(注意:屏幕边界点最多也是被添加3遍)。
  • 最后再依次添加S2、S3、S4点构成闭环就可以了。

总结一下规律,我们需要从屏幕四个角的任意一个点开始,假设是S1点,然后依次添加区域A、区域B、区域C等区域的点,区域点添加完一圈后,一定要把区域的第一个点再添加一遍,然后再去添加另一个区域的点,添加完后,依然要再加一遍该区域的第一个点,如果当前区域是最后一个区域了,那么添加完后,需要让它原路返回,也就是说除了最后一个区域的起点是填加两遍其他区域的起点都是添加三遍,添加完后,再添加一遍屏幕的S1点,最后就是按照顺时针或者逆时针添加屏幕的剩余三个点,添加完三个点后,必须再添加S1点,构成闭合(此时点被添加三遍)。

这样我们就只需要绘制这么一个整合后的阴影区域就可以了。由此就实现了我们的去雾霾目的。

过程有点绕,可能不太好理解,那怎么办,多看几遍然后自己试一试就可以了。demo还是之前的给你的地图模块动手术的demo。代码比较多,但是却很简单,所以文章里就不写代码了,本文介绍的关键在于这种思路,使用的时候,只需要借鉴思路,并且这种思路是通用的,移动端与web端都适用。

为了方便大伙,下面给出对数据的程序处理。

    /*从self.locationArray中获取数据进行展示,
      里面存储的是一个个模型数组,模型是TestPolygonModel,有lng与lat属性
    */
   
    /*1、获取需要malloc的内存区域,由以下几个部分组成:
     •  6个屏幕点
     •  self.locationArray.count*2 - 1 计算多边形起点被多加的次数,
        后面的减一是因为最后一个数组的第一个点只需要多加一遍,其他的都是多加两遍,
        注意这里计算的是起点被多加的次数,而不是起点被添加的总次数。
     •  self.locationArray子数组中元素的个数和,self.locationArray存放的是经纬度模型数组。
     */
    NSInteger mallocCount = 0;//需要分配的内存大小,也就是经纬度数组中总共的点数,也就是上面提到的三部分之和
    NSInteger itemCount = 0;  //也就是self.locationArray子数组中经纬度模型的个数和
    NSInteger itemIndex = 0;  //coors下表
    for (int i = 0; i0; i--) {
        itemIndex ++;
        TestPolygonModel *startPolygon = self.locationArray[i-1][0];                      //获取model
        coors[itemIndex].latitude = [startPolygon.lat floatValue];
        coors[itemIndex].longitude = [startPolygon.lng floatValue];
    }
    
    /*4、添加屏幕的边界点*/
    /*再次添加屏幕的起点*/
    itemIndex ++;
    coors[itemIndex].longitude = self.mapView.region.center.longitude-self.mapView.region.span.longitudeDelta*1.5;
    coors[itemIndex].latitude = self.mapView.region.center.latitude-self.mapView.region.span.latitudeDelta*1.5;
    /*添加屏幕右下角的S2点*/
    itemIndex ++;
    coors[itemIndex].longitude = self.mapView.region.center.longitude+self.mapView.region.span.longitudeDelta*1.5;
    coors[itemIndex].latitude = self.mapView.region.center.latitude-self.mapView.region.span.latitudeDelta*1.5;
    /*添加屏幕右上角的S3点*/
    itemIndex ++;
    coors[itemIndex].longitude = self.mapView.region.center.longitude+self.mapView.region.span.longitudeDelta*1.5;
    coors[itemIndex].latitude = self.mapView.region.center.latitude+self.mapView.region.span.latitudeDelta*1.5;
    /*添加屏幕左上角的S4点*/
    itemIndex ++;
    coors[itemIndex].longitude = self.mapView.region.center.longitude-self.mapView.region.span.longitudeDelta*1.5;
    coors[itemIndex].latitude = self.mapView.region.center.latitude+self.mapView.region.span.latitudeDelta*1.5;
    /*再次添加屏幕左下角的S1点*/
    itemIndex ++;
    coors[itemIndex].longitude = self.mapView.region.center.longitude-self.mapView.region.span.longitudeDelta*1.5;
    coors[itemIndex].latitude = self.mapView.region.center.latitude-self.mapView.region.span.latitudeDelta*1.5;
    if (mallocCount == itemIndex+1) {
        BMKPolygon *polygonModel0 = [BMKPolygon polygonWithCoordinates:coors count:mallocCount];
        [self.mapView addOverlay:polygonModel0];
    }else{
        [SVProgressHUD showErrorWithStatus:@"计算错误"];
    }

好吧,作者比较懒,三篇文章,只留下了一个demo。

你可能感兴趣的:(给你的地图点灯)