MarkerClustererPlus: установить цвет/адрес значка независимо от размера

Я рисую несколько сотен тысяч точек с помощью MarkerClustererPlus и хочу установить группы значков кластера (цвет) на основе некоторого внешнего свойства (не на основе количества представленных маркеров).

Я думаю, что единственный способ сделать это — создать несколько объектов MarkerClusterer и передать другой объект options, но я чувствую, что при этом сильно пострадает производительность. Есть ли способ лучше?

Marker Clusterer Plus с масштабируемыми значками разного размера.

Учитывая изображение выше, я бы хотел, чтобы 139, 24 и 5 были желтыми, а 213, 25, 30 и 2 — красными; и если возможно, обновите их стили/параметры через setOptions:
mc.group[0].setOptions({"url": imgPath +lookupThreshold(severity)+ '.svg' });
mc.group[1].setOptions({"url": imgPath +lookupThreshold(severity)+ '.svg' });

P.S. Если кому-то интересно, я настроил библиотеку, чтобы значок кластера масштабировался до своего размера, предоставив изображение svg и увеличив ширину и высоту в объекте параметров:

var mcOptions = {
  "styles": [{
    "height": 19,
    "url": img/map/clusters/",
    "width": 19
  },{
    "height": 24,
    "url": img/map/clusters/",
    "width": 24
  }, {…}]
};
for ( var s = mcOptions.styles.length-1; s >= 0; s-- )
{ mcOptions.styles[s].url += lookupThreshold(severity) + '.svg'; }
// lookupThreshold switches severity and returns a string: red, orange, …

Затем добавил следующее к markerclusterer.js:

line 275: this.backgroundSize_ = style.backgroundSize || "contain";
line 300: style.push('background-size:' + this.backgroundSize_ + ';');

Работает в Ffx 19.0.2, Chrome 26.x, Chrome Canary 28.x, Safari 6.0.2, IE 9.0.8 (но не в Opera 12.15).

EDIT Похоже, что создание нескольких экземпляров MarkerClusterer не сильно влияет на производительность; однако оказывается, что объект свойств/параметров, переданный MC, общий для экземпляров MC.

Решено Мне пришлось изменить библиотеку MarkerClustererPlus возле строки 665, чтобы клонировать opt_options (библиотека использовала ссылку, из-за чего все предыдущие opt_options были перезаписаны самой новой/последней переданной).


person Jakob Jingleheimer    schedule 15.04.2013    source источник
comment
Вы проверили эту ссылку? google-maps-utility-library- v3.googlecode.com/svn/trunk/   -  person Fabi    schedule 09.05.2013
comment
@Фаби, да. Причина, по которой кластеры являются разными кластерами, заключается в том, что они имеют разные размеры. Я хочу, чтобы все размеры определенной группы кластеров имели одинаковый цвет (но различались по размеру); разные группы должны иметь разные цвета.   -  person Jakob Jingleheimer    schedule 09.05.2013
comment
На данный момент я не вижу другого решения, кроме того, что у вас есть - несколько экземпляров, поскольку это разные группы.   -  person Fabi    schedule 09.05.2013


Ответы (1)


Получается, что проблема исходила от MarkerClustererPlus lib сама:

656:  function MarkerClusterer(map, opt_markers, opt_options) {
…
665:    opt_options = opt_options || {};

Строка 665 создает ссылку на существующий объект вместо новой копии. Я не мог использовать MarkerClusterer.prototype.extend из строки 1539, потому что он не делает глубокой копии (и расширяет только прототип объекта).

Итак, я написал свою собственную функцию глубокого копирования (jsfiddle), которую я сделал глобально доступной (скорее чем добавить его в прототипы как Array, так и Object):

function deepCopy(obj) {  
  this.cloneArr = function (arr) {
    var newArr = [];
    for ( var i = arr.length-1; i >= 0; i-- ) newArr[i] = this.evalObj( arr[i] );
    return newArr;
  };
  this.cloneObj = function(obj) {
    var newObj = {};
    for ( var prop in obj ) newObj[prop] = this.evalObj( obj[prop] );
    return newObj;
  };
  this.evalObj = function(obj) {
    switch ( typeof obj ) {
      case 'object':
        if ( Array.isArray( obj ) ) return this.cloneArr( obj );
        if ( obj instanceof Date === false ) return this.cloneObj( obj );
        // pass thru dates, strings, numbers, booleans, and functions
      default: return obj; // primitive
    }
  };
  return this.evalObj(obj);
}

Затем я изменил MarkerClustererPlus.js на следующее:

656:  function MarkerClusterer(map, opt_markers, opt_optionsG) {
…
665:    var opt_options = deepCopy( opt_optionsG ) || {};

Я протестировал наличие 5 экземпляров MarkerClustererPlus (каждый с 5000 маркеров, всего 25000), и не было заметного влияния на производительность по сравнению с одним экземпляром MC+.

Снимок экрана нескольких экземпляров MarkerClustererPlus

person Jakob Jingleheimer    schedule 10.05.2013
comment
Очень помогло!куда добавить функцию deepCopy?и как ваш подробный код в html для изменения цвета?Спасибо - person Orz; 13.07.2015
comment
По моему ответу поставил глобально (прикреплен к window). Цвет маркеров контролируется SVG, предоставленным в свойстве url. - person Jakob Jingleheimer; 13.07.2015