Olá, meu nome é Daria e sou o desenvolvedor frontend da unidade Geo em Avito. Gostaria de compartilhar minha experiência de como fizemos uma nova pesquisa de mapas na web, substituindo os clusters por uma solução mais conveniente e removendo a limitação do número de objetos exibidos.
Neste artigo, contarei qual era nossa tarefa e como lidamos com os problemas no processo de implementação.
, — . — , . — .
. -, , . -, — . , .
:
, , , , . , — .
, . , , .
, , , . — . , , . , , , . :
, , .
, . , . :
- ( );
- ( , );
- , , ( ).
:
— . , —
, —
, , —
, , , .
, 1000 . , , . , :
-, API . , ObjectManager, , 1000. , , 3000 , .
API , ( png svg ) , X, Y Z. , - . , API , ( ), - .
. . —
, . .
, :
func (*Tile) Deg2num(t *Tile) (x int, y int) {
x = int(math.Floor((t.Long + 180.0) / 360.0 * (math.Exp2(float64(t.Z)))))
y = int(math.Floor((1.0 - math.Log(math.Tan(t.Lat*math.Pi/180.0)+1.0/math.Cos(t.Lat*math.Pi/180.0))/math.Pi) / 2.0 * (math.Exp2(float64(t.Z)))))
return
}
func (*Tile) Num2deg(t *Tile) (lat float64, long float64) {
n := math.Pi - 2.0*math.Pi*float64(t.Y)/math.Exp2(float64(t.Z))
lat = 180.0 / math.Pi * math.Atan(0.5*(math.Exp(n)-math.Exp(-n)))
long = float64(t.X)/math.Exp2(float64(t.Z))*360.0 - 180.0
return lat, long
}
Go, .
svg , :
, GET- . :
const createTilesUrl = (tileNumber, tileZoom) => {
// params - , GET-
return `/web/1/map/tiles?${params}&z=${tileZoom}&x=${tileNumber[0]}&y=${tileNumber[1]}`;
};
const tilesLayer = new window.ymaps.Layer(createTilesUrl, { tileTransparent: true });
ymap.layers.add(tilesLayer);
, Layer, :
, 15-30 , 5000 rps. , . , .
, , . . . , , , 4, 25.
. , .
Redis -, , . , , , . , .
, , , . , .
Redis . , , , , . Redis in-memory. Redis.
, , . in-memory cache , . -. :
99 ~140 ms. 99% . : ~230 ms .
: , , . , svg. , .
, . .
,
. , . — , , 50 . , . , , , . — , . , , — , .
, . , . , , . — . , . , , . , , — , , id . , .
. — , - , . , . 10 forEach .
. . localStorage 1000 id . Ids , . , , localStorage.
, . , — , — . .
, -. /, , , . .
svg . - .
-
-
, — .