Динамическое создание иконок для кластеров

Требуется генерить "на лету" кастомные иконки для кластеров, в которых предполагается отрисовывать данные для кластеризуемых меток (несколько диаграмм; что-то похожее делает layout.PieChart).

Что-то похожее сейчас делаю для меток, засовывая в iconImageHref при создании маркера тело svg в виде data:image/svg+xml;charset=UTF-8,<svg ... />.

Для кластеров пока использую templateLayoutFactory (в поле clusterIconContentLayout кластеризатора) для вывода текста внутрь иконки и подсовываю иконку для значка clusterIcons: [{ href: clusterIconSrc, size: [60, 60], width: [-30, -30] }] (в свойствах для Clusterer).

Решением проблемы была бы возможность, напр., передавать функцию, которая создавала бы url с кастомным svg или полностью весь объект clusterIcons.

Пока способа делать что-то подобное не вижу.

Пробовал добраться до внутренних модулей api, но пока ничего нащупал. Напр., как-то так (по-моему, переопределение вообще не работает; с ym давно не сталкивался, наверное, что-то не так делаю):

modules.define('theme.islands.cluster.layout.Icon', ['theme.islands.cluster.layout.Icon'], override(provide, baseIcon) => {
  const overrided = Object.assign({}, baseIcon, {
    getShape: function getShape(geometry) { /*...*/ },
  })
  provide(overrided)
})

Используется:

  • ymaps api v2.1.79
  • react-yandex-maps v4.6.0

Ответы (1 шт):

Автор решения: lilliputten

Возможное решение: переопределяем метод Clusterer.prototype.createCluster, в котором задаём параметр свойств кластеризатора clusterIcons с динамически создаваемым (в зависимости от кол-ва кластеризуемых объектов и их свойств) свойством href для иконки значка кластера:

// Save original `createCluster` method...
const origCreateCluster = Clusterer.prototype.createCluster
// Override `createCluster` method...
Clusterer.prototype.createCluster = function overrideCreateCluster(center, geoObjects) {
  // Fetch clustered objects data...
  const objData = geoObjects.map(geoObj => ({ id: geoObj.options.get('id') }))
  // Generate `clusterIcons` object with custom icon src...
  const iconSrc = getClusterIconSrcByObjData(objData)
  const clusterIconsEntry = { ...defaultClusterIconsEntry, href: iconSrc }
  this.options.set('clusterIcons', [clusterIconsEntry])
  // Get cluster placemark content...
  return origCreateCluster.call(this, center, geoObjects)
}

Этот метод работает, за исключением того, что вместо url с data:image/svg+xml;charset=UTF-8,<svg надо использовать url в кодировке base64L data:image/svg+xml;base64,... (с помощью btoa, напр.). .

→ Ссылка