在上一篇說(shuō)到10000個(gè)數(shù)據(jù)用時(shí)300ms左右,這里可以舉報(bào)作者謊報(bào)數(shù)據(jù)了,為什么呢,各位看官你細(xì)聽分說(shuō),因?yàn)楫?dāng)時(shí)測(cè)試的是生成兩個(gè)標(biāo)記圖片的10000個(gè)數(shù)據(jù),所以耗時(shí)大概300ms就說(shuō)的過(guò)去了,經(jīng)過(guò)檢查300ms主要有這幾個(gè)部分產(chǎn)生消耗,分別是:①刪除臨時(shí)存儲(chǔ)圖片時(shí)會(huì)產(chǎn)生大概50-100ms,看圖片多少因?yàn)槲业牟僮魇侵苯觿h除所有圖片;②canvas畫圖每張圖片會(huì)產(chǎn)生55ms左右;③init_calculation方法處理10000個(gè)數(shù)據(jù)時(shí)產(chǎn)生消耗。那么我也就是在這三個(gè)方面對(duì)代碼進(jìn)行了優(yōu)化。
因?yàn)閏anvas畫的圖片是一個(gè)臨時(shí)路徑所以沒(méi)辦法必須得進(jìn)行存儲(chǔ),當(dāng)然圖片大小基本是2000字節(jié)左右存儲(chǔ)的時(shí)間大概5ms可以忽略不計(jì),然后有的朋友會(huì)說(shuō)萬(wàn)一很多圖片呢,那也會(huì)是很大的消耗,確實(shí),但是別急處理之后就不會(huì)有那么多圖片了。
優(yōu)化處理一:初次加載的時(shí)候是直接精準(zhǔn)定位到一個(gè)標(biāo)記點(diǎn),這個(gè)時(shí)候我只需要處理這一個(gè)標(biāo)記點(diǎn)和其他標(biāo)記之間是否存在合并的情況, 沒(méi)有的話就根本不用進(jìn)行畫圖存儲(chǔ)的操作,有的話也就只需要處理一張圖片。
調(diào)用以及渲染標(biāo)記點(diǎn)的優(yōu)化
mapdata=this.canvas_map.init_mapdata(JSON.stringify(this.Variable.data),this.on_id,this.scale)
this.equipMentname=mapdata.equipMentdata.markers.name
this.latitude= mapdata.equipMentdata.markers.latitude
this.longitude= mapdata.equipMentdata.markers.longitude
if(mapdata.markers.quantity>1){
buffer_obj={}
buffer_obj.key_id=mapdata.markers.id
buffer_obj.quantity=mapdata.markers.quantity
this.markers_id.push(buffer_obj)
await this.draw(mapdata.markers.quantity,mapdata.markers.id).then(res=>{
if(res){
mapdata.markers.iconPath=res
}
})
}
初始化處理的優(yōu)化
Canvasmap.prototype.init_calculation = function(data,markers,scale){
this.markers=null
var distance=this.regionchange_scale(scale)
var res
this.markers=markers
this.BufferArray=[]
for(let i=0;i<data.length;i++){
res=this.Calculate_distance(this.markers.longitude,this.markers.latitude,data[i].markers.longitude,data[i].markers.latitude)
if(res<distance){
console.log(data[i])
this.markers.quantity++
}
}
};
優(yōu)化處理二:前面說(shuō)到存儲(chǔ)圖片和畫圖消耗比較大,于是這邊處理是每畫一次圖片會(huì)按標(biāo)記點(diǎn)的特有id,對(duì)應(yīng)標(biāo)記數(shù)記錄quantity和存儲(chǔ)路徑進(jìn)行存儲(chǔ)到數(shù)組里面,那么在下一次遇到這個(gè)id時(shí)會(huì)先去數(shù)組里面查找如果已經(jīng)存在但是quantity有改變那么我們進(jìn)行畫圖更新這時(shí)我們只刪除一張圖片而不是之前刪除所有存儲(chǔ)的圖片;不存在這個(gè)id那就從頭畫圖和存儲(chǔ)并記錄到數(shù)組;如果各個(gè)單位都沒(méi)有改變那么我們就直接復(fù)用,因?yàn)檫@個(gè)時(shí)候圖片還是存在內(nèi)存里面直接根據(jù)id拿路徑顯示就可以了,就和vue中diff算法處理虛擬dom有點(diǎn)類似。
//對(duì)比最新標(biāo)記和存儲(chǔ)的標(biāo)記數(shù)據(jù)進(jìn)行對(duì)比是否為重復(fù)標(biāo)記
let diff_id=this.markers_id.findIndex(item=>item.key_id==mapdata.markers[i].id)
if(mapdata.markers[i].quantity>1){
if(diff_id!=-1&&this.markers_id[diff_id].quantity!=mapdata.markers[i].quantity){ this.markers_id[diff_id].quantity=mapdata.markers[i].quantity
await this.rmfile(this.markers_id[diff_id].path)
await this.draw(mapdata.markers[i].quantity,this.markers_id[diff_id].key_id).then(res=>{
if(res){
mapdata.markers[i].iconPath=res
}
})
//如果之前沒(méi)有存在過(guò)這個(gè)標(biāo)記那么直接push新路徑
}else if(diff_id==-1){
this.markers_id.push({
'key_id':mapdata.markers[i].id,
'quantity':mapdata.markers[i].quantity
})
await this.draw(mapdata.markers[i].quantity,mapdata.markers[i].id).then(res=>{
if(res){
mapdata.markers[i].iconPath=res
}
})
//否則直接復(fù)用
}else{
mapdata.markers[i].iconPath=this.markers_id[diff_id].path
}
}else{
mapdata.markers[i].iconPath="/static/img/onselect.png"
}
優(yōu)化處理三:因?yàn)榈貓D的縮放級(jí)別是不斷在變化的,我們不可能每次都計(jì)算所有的標(biāo)記點(diǎn),看不到的就可以假裝不存在,所以對(duì)標(biāo)記進(jìn)行篩選每次只處理視野范圍內(nèi)的標(biāo)記
//獲取地圖可視經(jīng)緯度范圍,對(duì)不在視野范圍內(nèi)的標(biāo)記去除(提升效率3)
getRegion(map,list){
let mapsection_data=[]
return new Promise((resolve, reject)=>{
map.getRegion ({
success(res) {
let N_longitude=res.northeast.longitude
let N_latitude=res.northeast.latitude
let S_longitude=res.southwest.longitude
let S_latitude=res.southwest.latitude
for(let i=0;i<list.length;i++){
if(list[i].markers.longitude<N_longitude&&list[i].markers.latitude<N_latitude&&list[i].markers.longitude>S_longitude&&list[i].markers.latitude>S_latitude){
mapsection_data.push(list[i])
}
}
resolve(mapsection_data)
}
})
})
},
優(yōu)化處理四:前面還說(shuō)到為什么圖片的數(shù)量會(huì)變的很少,而且是越來(lái)越少,因?yàn)槊看味歼M(jìn)行了記錄,但是當(dāng)縮放級(jí)別越來(lái)越小,這時(shí)候視野越廣要處理的標(biāo)記點(diǎn)會(huì)越來(lái)越多,是有這么個(gè)問(wèn)題,所以考慮之后決定在按地市到省份地理位置進(jìn)行處理,不過(guò)在幾萬(wàn)個(gè)數(shù)據(jù)計(jì)算所有標(biāo)記點(diǎn)的合并情況也是很有壓力的,我的處理方式是在第一次打開當(dāng)前標(biāo)記點(diǎn)時(shí)另外異步一個(gè)方法開始計(jì)算,這樣等地圖到達(dá)級(jí)市,省級(jí)的時(shí)候應(yīng)該已經(jīng)處理完,便可以直接拿數(shù)據(jù)走流程了。
getRegeo(data){
return new Promise((resolve, reject) => {
this.myAmapFun = new amapFile.AMapWX({key:'0ac92fa7d5fe9244fa0139b16a3a2c21'});
this.myAmapFun.getRegeo({
location:''+data.markers.longitude+','+data.markers.latitude,
success: (data)=>{
let province=data[0].regeocodeData.addressComponent
let province_index=this.province.findIndex(item=>item.markers.name==province.province)
if(province_index!=-1){
this.province[province_index].markers.quantity++
let city_index=this.province[province_index].city.findIndex(item=>item.markers.name==province.city)
if(city_index>-1){
this.province[province_index].city[city_index].markers.quantity++
}else{
this.province[province_index].city.push({
"markers":{
"latitude": data[0].latitude,
"longitude": data[0].longitude,
"iconPath": "/static/img/onselect.png",
"width": 32,
"height":32,
"quantity":1,
"id": province.adcode,
"title":province.city+"設(shè)備",
"name": province.city,
"address":province.city
}})
}
}
resolve(this.province)
},
fail: function(info){
console.log(info)
}
})
});
},
但是問(wèn)題就在這個(gè),這個(gè)是通過(guò)高德api接口去獲取定位,等他處理完上萬(wàn)個(gè)數(shù)據(jù)黃花菜都涼了,當(dāng)前只是模擬數(shù)據(jù),最終可以和后臺(tái)約定好數(shù)據(jù)結(jié)構(gòu)直接將數(shù)據(jù)返回給你,可以在進(jìn)入頁(yè)面之前就拿到,一頓操作下來(lái)我這邊算是比較流暢了。
另外頁(yè)面上的模糊搜索功能如果要使用還需自行進(jìn)行處理,組件是沒(méi)有問(wèn)題,代碼里面是通過(guò)名字字段name進(jìn)行搜索。
方法可能不是最優(yōu)但是也能夠?qū)⒕?,如有想法可另行修改,代碼已經(jīng)更新到git倉(cāng)庫(kù),可以去上一篇底部鏈接獲取。