Comment nous avons dessiné plusieurs milliers d'objets interactifs sur la carte sans nuire aux performances

Bonjour, je m'appelle Daria et je suis le développeur Frontend de l'unité Geo d'Avito. Je souhaite partager mon expérience de la manière dont nous avons effectué une nouvelle recherche cartographique sur le Web, en remplaçant les clusters par une solution plus pratique et en supprimant la limitation du nombre d'objets affichés.



Dans cet article, je vais vous dire quelle était la tâche et comment nous avons traité les problèmes dans le processus de mise en œuvre.





Pourquoi l'ancienne recherche cartographique ne nous convenait pas



Auparavant, dans la recherche sur la carte, les annonces étaient affichées en grappes, et lors d'un zoom avant ou sur un petit échantillon, elles étaient affichées avec des épingles. Les clusters sont lorsque des objets proches sur la carte sont rassemblés dans un grand groupe, indiqué par un cercle avec un nombre. Une épingle est un objet avec des publicités dans la maison.



    . -,      ,       . -,  — .    , .



:







,  , , ,     . ,    — .



 ,   .   , ,   .



      , , , .  —  .     , , . ,    , , . :



limit=viewPort.width×viewPort.height/(pinDiameter2×9)



, , .



   , .   , .   :



  •   ( );
  •   ( , );
  • ,   ,   (  ).


    :





  — . ,  —





,  —





, , —



,     , , .





  ,   1000 .     , , . , :





 



-, API . ,   ObjectManager,  ,   1000.   , , 3000 ,    .



,    .   API - — ,   Layer.



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  .  - .





-





-





,       —   .




All Articles