Hola, mi nombre es Daria y soy la desarrolladora Frontend de la unidad Geo en Avito. Quiero compartir mi experiencia de cómo hicimos una nueva búsqueda de mapas en la web, reemplazando los clústeres con una solución más conveniente y eliminando la limitación en la cantidad de objetos mostrados.
En este artículo te contaré cuál fue nuestra tarea y cómo manejamos los problemas en el proceso de implementación.
, — . — , . — .
. -, , . -, — . , .
:
, , , , . , — .
, . , , .
, , , . — . , , . , , , . :
, , .
, . , . :
- ( );
- ( , );
- , , ( ).
:
— . , —
, —
, , —
, , , .
, 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 . - .
-
-
, — .