曾經(jīng)坐在飛機(jī)上俯瞰整個(gè)北京城,在萬米高空上可以看到北京的全貌但荤,即使是凌晨一兩點(diǎn)罗岖,北京依然燈火通明,儼然是一座不眠之城腹躁。四通八達(dá)的交通線仿佛是這座城市的血脈桑包,里面流淌著的,是生活在這里的人們的夢想纺非。
然而哑了,今天要講的不是北京,也不是夢想烧颖。今天要講的是我們該如何在地圖上點(diǎn)起一盞燈弱左,就像夜幕下的北京城一樣。
為了方便理解炕淮,我們先看一下最終的實(shí)現(xiàn)效果拆火。
沒錯(cuò),就是要在夜幕下涂圆,放幾盞燈榜掌,告訴別人這塊區(qū)域目前有人正在里面工作。
在講解如何實(shí)現(xiàn)這種效果前乘综,先分享一下之前的那種存在問題的思路憎账。
之前的做法是:
- 位于底部的陰影區(qū)域當(dāng)做一個(gè)大的
PolygonView
,并且充滿屏幕卡辰。 - 位于上面的高亮區(qū)域當(dāng)做另外的
PolygonView
胞皱,依次添加,并設(shè)置它們的背景色與透明度九妈,模擬高亮反砌。
然而這樣做會(huì)產(chǎn)生一個(gè)無法避免的問題,那就是無論我們怎么設(shè)置高亮區(qū)域的背景色與透明度,都不夠好看:透明度低的時(shí)候萌朱,就看不到下面的地圖宴树,透明度高的時(shí)候,雖然能看到下面的地圖晶疼,但是卻霧蒙蒙的酒贬,仿佛那片高亮區(qū)域又憨,被霧霾籠罩了。锭吨。
那么問題來了蠢莺,如何讓大晚上還在工作的人們,少呼吸點(diǎn)霧霾呢零如。
思路其實(shí)很簡單躏将,只需要換個(gè)角度來思考就可以了,那就是我們不再分別繪制高亮區(qū)域和底部的全屏陰影區(qū)域考蕾,而是只需要繪制一個(gè)陰影區(qū)域就可以了祸憋,這樣剩下的沒有繪制的區(qū)域自然就是沒有霧霾的。
對(duì)肖卧,再說一遍蚯窥,只需要繪制一個(gè)陰影區(qū)域就可以。
先來一張圖:
屏幕的四個(gè)點(diǎn)分別是S1喜命、S2、S3河劝、S4
,兩個(gè)高亮區(qū)域分別是區(qū)域A
和區(qū)域B
壁榕,區(qū)域A的四個(gè)點(diǎn)分別是A1、A2赎瞎、A3牌里、A4,區(qū)域B的四個(gè)點(diǎn)分別是B1务甥、B2牡辽、B3、B4敞临。我們要繪制的就是除去區(qū)域A,區(qū)域B
后态辛,把剩下的那部分當(dāng)做一個(gè)PolygonView
來繪制。(注意:這里所說的點(diǎn)是指經(jīng)緯度點(diǎn)挺尿,而不是point點(diǎn))
So
,如何得到陰影區(qū)域的Polygon
:
- 首先聲明一個(gè)經(jīng)緯度數(shù)組
CLLocationCoordinate2D * coors
奏黑,用來存放區(qū)域坐標(biāo)點(diǎn)。 - 先從
S1點(diǎn)
開始编矾,將其加入到coors
中熟史,下一個(gè)點(diǎn)是A1點(diǎn)
,然后依次添加A2窄俏、A3蹂匹、A4
。 - 添加完
A4
后凹蜈,** 一定要再將A1點(diǎn)
加一遍**,以構(gòu)成一個(gè)閉環(huán)限寞,而不是直接去添加區(qū)域B的點(diǎn)忍啸,此時(shí)A1點(diǎn)
被添加了兩遍。 - 接著添加
區(qū)域B
的點(diǎn)昆烁,先是B1點(diǎn)
吊骤,然后依次添加B2、B3静尼、B4
白粉。 - 添加完
B4
后,像區(qū)域A
一樣鼠渺,一定要再添加一遍B1點(diǎn)
鸭巴,以構(gòu)成閉環(huán)。此時(shí)B1點(diǎn)
被添加兩遍拦盹。 - 由于此時(shí)只有兩個(gè)區(qū)域鹃祖,所以添加完
B1點(diǎn)
后,我們需要返回普舆,這里需要注意的一定要原路返回恬口。所以需要再添加一遍A1點(diǎn)
,此時(shí)A1點(diǎn)
被添加了3遍(注意:非屏幕邊界點(diǎn)最多被添加三遍)沼侣。 - 接著我們需要再次添加
S1點(diǎn)
祖能,也就是說從S1點(diǎn)
,出去轉(zhuǎn)了一圈后蛾洛,最后必須回到S1點(diǎn)
养铸。此時(shí)S1點(diǎn)
被添加2遍。(注意:屏幕邊界點(diǎn)最多也是被添加3遍)轧膘。 - 最后再依次添加
S2钞螟、S3、S4
點(diǎn)構(gòu)成閉環(huán)就可以了谎碍。
總結(jié)一下規(guī)律鳞滨,我們需要從屏幕四個(gè)角的任意一個(gè)點(diǎn)
開始,假設(shè)是S1點(diǎn)
蟆淀,然后依次添加區(qū)域A太援、區(qū)域B、區(qū)域C
等區(qū)域的點(diǎn)扳碍,區(qū)域點(diǎn)添加完一圈后提岔,一定要把區(qū)域的第一個(gè)點(diǎn)再添加一遍,然后再去添加另一個(gè)區(qū)域的點(diǎn)
笋敞,添加完后碱蒙,依然要再加一遍該區(qū)域的第一個(gè)點(diǎn)
,如果當(dāng)前區(qū)域是最后一個(gè)
區(qū)域了,那么添加完后赛惩,需要讓它原路返回
哀墓,也就是說除了最后一個(gè)區(qū)域的起點(diǎn)是填加兩遍
,其他區(qū)域的起點(diǎn)都是添加三遍
喷兼,添加完后篮绰,再添加一遍屏幕的S1點(diǎn)
,最后就是按照順時(shí)針或者逆時(shí)針添加屏幕的剩余三個(gè)點(diǎn),添加完三個(gè)點(diǎn)后季惯,必須再添加S1點(diǎn)吠各,構(gòu)成閉合(此時(shí)點(diǎn)被添加三遍)。
這樣我們就只需要繪制這么一個(gè)整合后的陰影區(qū)域就可以了勉抓。由此就實(shí)現(xiàn)了我們的去霧霾目的贾漏。
過程有點(diǎn)繞,可能不太好理解藕筋,那怎么辦纵散,多看幾遍然后自己試一試就可以了。demo還是之前的給你的地圖模塊動(dòng)手術(shù)的demo隐圾。代碼比較多伍掀,但是卻很簡單,所以文章里就不寫代碼了暇藏,本文介紹的關(guān)鍵在于這種思路蜜笤,使用的時(shí)候,只需要借鑒思路叨咖,并且這種思路是通用的瘩例,移動(dòng)端與web端都適用啊胶。
為了方便大伙甸各,下面給出對(duì)數(shù)據(jù)的程序處理。
/*從self.locationArray中獲取數(shù)據(jù)進(jìn)行展示焰坪,
里面存儲(chǔ)的是一個(gè)個(gè)模型數(shù)組趣倾,模型是TestPolygonModel,有l(wèi)ng與lat屬性
*/
/*1某饰、獲取需要malloc的內(nèi)存區(qū)域儒恋,由以下幾個(gè)部分組成:
? 6個(gè)屏幕點(diǎn)
? self.locationArray.count*2 - 1 計(jì)算多邊形起點(diǎn)被多加的次數(shù),
后面的減一是因?yàn)樽詈笠粋€(gè)數(shù)組的第一個(gè)點(diǎn)只需要多加一遍黔漂,其他的都是多加兩遍诫尽,
注意這里計(jì)算的是起點(diǎn)被多加的次數(shù),而不是起點(diǎn)被添加的總次數(shù)炬守。
? self.locationArray子數(shù)組中元素的個(gè)數(shù)和牧嫉,self.locationArray存放的是經(jīng)緯度模型數(shù)組。
*/
NSInteger mallocCount = 0;//需要分配的內(nèi)存大小,也就是經(jīng)緯度數(shù)組中總共的點(diǎn)數(shù)酣藻,也就是上面提到的三部分之和
NSInteger itemCount = 0; //也就是self.locationArray子數(shù)組中經(jīng)緯度模型的個(gè)數(shù)和
NSInteger itemIndex = 0; //coors下表
for (int i = 0; i<self.locationArray.count; i++) {
itemCount = itemCount + [self.locationArray[i] count];
}
mallocCount = 6 + self.locationArray.count * 2 - 1 + itemCount;
/*2曹洽、正序計(jì)算,無論是不是最后一個(gè)數(shù)組辽剧,先依次將該數(shù)組的點(diǎn)加進(jìn)去送淆,加完后再加一遍該數(shù)組中的第一個(gè)點(diǎn)。*/
CLLocationCoordinate2D * coors = (CLLocationCoordinate2D *)malloc(mallocCount * sizeof(CLLocationCoordinate2D));
/*添加屏幕左下角的S1點(diǎn)*/
coors[0].longitude = self.mapView.region.center.longitude-self.mapView.region.span.longitudeDelta*1.5;
coors[0].latitude = self.mapView.region.center.latitude-self.mapView.region.span.latitudeDelta*1.5;
/*正序添加每一個(gè)數(shù)組中的所有元素*/
for (int i = 0; i < self.locationArray.count; i++) {
NSArray *polygonArray = self.locationArray[i];
for (int j = 0; j<polygonArray.count; j++) {
TestPolygonModel *polygonModel = self.locationArray[i][j]; //獲取model
itemIndex++;
coors[itemIndex].longitude = [polygonModel.lng floatValue];
coors[itemIndex].latitude = [polygonModel.lat floatValue];
}
//添加完每一組的元素后怕轿,需要再添加一遍該組的第一個(gè)點(diǎn)偷崩,
itemIndex ++;
TestPolygonModel *startPolygon = polygonArray[0];
coors[itemIndex].latitude = [startPolygon.lat floatValue];
coors[itemIndex].longitude = [startPolygon.lng floatValue];
}
/*3、倒敘添加每一組的第一個(gè)元素撤卢,但是最后一個(gè)組不需要添加环凿,因?yàn)樽詈笠粋€(gè)組總共只需要加兩遍,所以過濾掉最后一組*/
for (NSInteger i = self.locationArray.count - 1; i>0; i--) {
itemIndex ++;
TestPolygonModel *startPolygon = self.locationArray[i-1][0]; //獲取model
coors[itemIndex].latitude = [startPolygon.lat floatValue];
coors[itemIndex].longitude = [startPolygon.lng floatValue];
}
/*4放吩、添加屏幕的邊界點(diǎn)*/
/*再次添加屏幕的起點(diǎn)*/
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點(diǎn)*/
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點(diǎn)*/
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點(diǎn)*/
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點(diǎn)*/
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:@"計(jì)算錯(cuò)誤"];
}
好吧智听,作者比較懶,三篇文章渡紫,只留下了一個(gè)demo到推。