Мозаичные слои

Выберите платформу: Android iOS JavaScript

Можно добавлять изображения поверх карты в виде мозаичных слоев. Слои фрагментов размещаются поверх фрагментов карты при определенном уровне масштабирования. Если у вас достаточно фрагментов карты, вы можете дополнить геоданные Google для всей карты на нескольких уровнях масштабирования.

Введение

Слои фрагментов, или наложения фрагментов, позволяют размещать изображения поверх фрагментов базовой карты Google. С помощью этой функции вы можете добавлять в приложение данные, например информацию о достопримечательностях или дорожном движении, а также местные снимки. В сочетании с типом карты kGMSTypeNone слои фрагментов позволяют заменять данные базовой карты Google собственными.

Слои мозаики используются, когда на карту нужно добавить большое количество изображений, покрывающих значительные географические области. Если вам нужно закрепить одно изображение на небольшом участке карты, используйте наземное наложение.

Координаты фрагмента

Maps API разбивает изображения на каждом уровне масштабирования на набор квадратных фрагментов карты, расположенных в виде сетки. Когда карта прокручивается до нового местоположения или до нового уровня масштабирования, Maps API определяет, какие плитки необходимы, и преобразует это в набор плиток для получения.

В проекции Меркатора, реализованной Google, фрагмент с координатами (0,0) всегда находится в северо-западном углу карты. Значения x увеличиваются с запада на восток, а значения y – с севера на юг. Фрагменты индексируются с использованием координат x,y относительно исходной точки. Например, при уровне масштабирования 2 (земная поверхность делится на 16 фрагментов) каждый фрагмент можно обозначить уникальной парой значений x,y:

Карта мира, разделенная на четыре сектора по горизонтали и четыре по вертикали.

Размер каждого листа карты составляет 256x256 точек. На уровне масштабирования 0 карта всего мира отображается как один фрагмент. На каждом следующем уровне масштаб увеличивается вдвое. Например, на первом уровне масштабирования карта будет отображаться в виде сетки фрагментов 2 x 2, на втором – 4 x 4, на третьем – 8 x 8 и так далее. Чтобы создать наложения, подготовьте по одному изображению размером 256 x 256 точек для каждого фрагмента на каждом уровне масштабирования, который вы хотите поддерживать.

Добавление слоя фрагментных наложений

  1. Создайте экземпляр объекта GMSURLTileLayer или пользовательского подкласса GMSTileLayer или GMSSyncTileLayer.
  2. При необходимости измените свойство zIndex, чтобы скорректировать положение слоя относительно других слоев.
  3. Назначьте объект GMSTileLayer карте, задав его свойство map.

Maps SDK для iOS предоставляет три класса, которые можно использовать для реализации слоя фрагментов. Для каждого класса необходимо определить, как получить правильный фрагмент карты для заданного набора координат {x,y,zoom}. Доступны следующие варианты:

  • Создайте подкласс GMSSyncTileLayer, реализующий метод tileForX:y:zoom, который возвращает экземпляры UIImage.
  • Создайте подкласс GMSTileLayer, реализующий асинхронный метод requestTileForX:y:zoom, который затем возвращает изображение фрагмента.
  • Используйте существующий класс GMSURLTileLayer, чтобы автоматически получать фрагменты из URL, предоставляя блок GMSTileURLConstructor. GMSURLTileLayer – это конкретный класс, который не может быть подклассом.

Если вы создаете подкласс GMSSyncTileLayer или GMSTileLayer, то, предоставив результат nil, вы сообщите Maps SDK для iOS, что данные недоступны, но могут стать доступны в будущем. Вы также можете вернуть значение kGMSTileLayerNoTile, чтобы указать, что в этом месте нет фрагмента.

Для GMSURLTileLayer возвращение nil из GMSTileURLConstructor будет означать, что в этом месте нет элемента.

Получение фрагментов по URL с помощью GMSURLTileLayer

Для GMSURLTileLayer не требуется создавать подкласс, но вам нужно будет реализовать блок GMSTileURLConstructor. В приведенном ниже коде показано, как использовать GMSURLTileLayer для отображения плана здания с несколькими этажами.

Swift

let floor = 1

// Implement GMSTileURLConstructor
// Returns a Tile based on the x,y,zoom coordinates, and the requested floor
let urls: GMSTileURLConstructor = { (x, y, zoom) in
  let url = "https://www.example.com/floorplans/L\(floor)_\(zoom)_\(x)_\(y).png"
  return URL(string: url)
}

// Create the GMSTileLayer
let layer = GMSURLTileLayer(urlConstructor: urls)

// Display on the map at a specific zIndex
layer.zIndex = 100
layer.map = mapView
      

Objective-C

NSInteger floor = 1;

// Create the GMSTileLayer
GMSURLTileLayer *layer = [GMSURLTileLayer tileLayerWithURLConstructor:^NSURL * _Nullable(NSUInteger x, NSUInteger y, NSUInteger zoom) {
  NSString *url = [NSString stringWithFormat:@"https://www.example.com/floorplans/L%ld_%lu_%lu_%lu.png",
                   (long)floor, (unsigned long)zoom, (unsigned long)x, (unsigned long)y];
  return [NSURL URLWithString:url];
}];

// Display on the map at a specific zIndex
layer.zIndex = 100;
layer.map = mapView;
      

Получение фрагментов в виде объектов UIImage с помощью GMSSyncTileLayer

GMSSyncTileLayer и GMSTileLayer – это абстрактные классы, предназначенные для создания подклассов. Эти классы можно использовать для показа элементов в виде UIImage. В примере ниже показано, как отобразить пользовательское изображение поверх некоторых фрагментов карты с помощью подкласса GMSSyncTileLayer.

Swift

class TestTileLayer: GMSSyncTileLayer {
  override func tileFor(x: UInt, y: UInt, zoom: UInt) -> UIImage? {
    // On every odd tile, render an image.
    if (x % 2 == 1) {
      return UIImage(named: "australia")
    } else {
      return kGMSTileLayerNoTile
    }
  }
}

      

Objective-C

@interface TestTileLayer : GMSSyncTileLayer
@end

@implementation TestTileLayer

- (UIImage *)tileForX:(NSUInteger)x y:(NSUInteger)y zoom:(NSUInteger)zoom {
  // On every odd tile, render an image.
  if (x % 2 == 1) {
    return [UIImage imageNamed:@"australia"];
  } else {
    return kGMSTileLayerNoTile;
  }
}

@end
      

Чтобы добавить слой на карту, создайте экземпляр объекта и задайте его свойство map.

Swift

let layer = TestTileLayer()
layer.map = mapView
      

Objective-C

GMSTileLayer *layer = [[TestTileLayer alloc] init];
layer.map = mapView;
      

Фрагменты с высоким разрешением для дисплеев Retina

Вы можете использовать изображения с высоким разрешением как с GMSSyncTileLayer, так и с GMSURLTileLayer, задав для tileSize значение 512. Свойство tileSize указывает количество пикселей, которое предпочтительно использовать для отображения возвращаемых изображений фрагментов. По умолчанию используется значение 256 – размер фрагмента Google Карт на устройстве без дисплея Retina.

Если вы показываете фрагменты с обычным значением dpi на устройстве с высоким dpi, вы можете увеличить изображения, задав для параметра tileSize значение 512. Обратите внимание, что при увеличении масштаба качество изображения может снизиться, особенно если на нем есть тонкие линии или текст. Для достижения наилучших результатов сопоставьте tileSize и DPI изображения с дисплеем. Карты, отображаемые на устройстве Retina, будут выглядеть лучше всего при показе изображений с высоким разрешением и значением tileSize, равным 512. На устройствах без Retina карты будут отлично выглядеть с обычными изображениями и значением tileSize по умолчанию, равным 256.

Как удалить устаревшие фрагменты

Если фрагменты слоя становятся неактивны, их можно принудительно обновить, вызвав метод clearTileCache. В результате все фрагменты в этом слое будут перезагружены.

Swift

layer.clearTileCache()
      

Objective-C

[layer clearTileCache];