Всплывающее окно маркера листовки Dc.js, отображающее поля из входных данных

Я новичок в dc.js, работающий над приборной панелью, отображающей информацию на графиках и на карте.

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

var facilities = xf.dimension(function(d) { return d.geo; });
var facilitiesGroup = facilities.group().reduceCount();

dc.leafletMarkerChart("#test .map",groupname)
  .dimension(facilities)
  .group(facilitiesGroup)
  .width(540)
  .height(440)
  .center([0,0])
  .zoom(7)
  .cluster(true)
  .filterByArea(true)
  .renderPopup(true)
  .popup();

Я попытался изменить всплывающее окно следующим образом:

  .popup(function(d,feature) { return feature.name +" : "+feature.items; });

Чтобы включить название места и количество предметов там. Тем не менее, всплывающие окна теперь просто упоминают "undefined: undefined".

Я уверен, что есть простое решение, которое я просто игнорирую из-за моего ограниченного опыта. Кто-нибудь может помочь?

2 ответа

Решение

Сердце dc.js и crossfilter - это своего рода карта и редукция, где для каждого значения находятся ячейки, а затем агрегируются строки, которые попадают в каждую ячейку.

Но похоже, что вы пытаетесь напрямую отобразить свои данные на листовой карте без какой-либо агрегации. Если вы хотите агрегировать, вам придется решить, как агрегировать items (вы не показали свои данные, поэтому я не знаю, что это такое), и, вероятно, придется оставить name потому что имена обычно не объединяются.

Поэтому я бы предложил указывать перекрестный фильтр для бина по имени (при условии, что оно уникально) вместо местоположения, а затем удерживать местоположение и элементы, а также вести подсчет. К сожалению, это несколько противоречит основной цели перекрестного фильтра, поэтому код немного неловкий:

var facilities = xf.dimension(function(d) { return d.name; });
var facilitiesGroup = facilities.group().reduce(
    function(p, v) { // add
        p.items = v.items;
        p.geo = v.geo;
        ++p.count;
        return p;
    },
    function(p, v) { // remove
        --p.count;
        return p;
    },
    function() { // init
        return {count: 0};
    }
);

Мы просто предполагаем, что имена уникальны, и извлекаем поля из первой записи, которую мы видим. Теперь группа кроссфильтров вернет массив пар ключ-значение, где имя будет key и {count, items, geo} будет значением, поэтому мы можем сказать dc-листовке, как их читать:

dc.leafletMarkerChart("#test .map",groupname)
    // ...
    .valueAccessor(function(kv) {
        return kv.value.count;
    })
    .locationAccessor(function(kv) {
        return kv.value.geo;
    })
    .popup(function(kv) {
        return kv.key + " : " + kv.value.items;
    })

kv это соглашение, которое я хотел бы использовать, чтобы напомнить себе, что данные d почти всегда будет пара ключ-значение. (В некоторых схемах постоянного тока это будет объект, который содержит data элемент, который является парой ключ-значение.)

Обратите внимание, что это отличается от поведения по умолчанию в dc-leaflet для агрегирования по местоположению и установки местоположения в качестве ключа. Если ваши местоположения гарантированно будут уникальными, вы также можете сделать это таким образом, но мне это кажется рискованным (данные могут быть потеряны). Я думаю, что лучше использовать действительно уникальный ключ, если вы хотите отобразить исходные данные без агрегирования.

В моем случае не работает листовка MarkerChart. Он не показал ни ошибок, ни всплывающих окон. Используя тот же подход к стандартной функции dc-leaflet.js, вы можете сделать следующее:

var restaurantsGroup = restaurantNames.group().reduce(
                    function(p, v) { // add
                    p.name = v.name;
                    p.price_range = v.price_range;
                    p.stars = v.stars;
                    p.latitude = v.latitude;
                    p.longitude = v.longitude;
            ++p.count;
            return p;
                },
                function(p, v) { // remove
                --p.count;
                return p;
                },
                function() { // init
                return {count: 0};
                }
            );


var marker = dc_leaflet.markerChart("#demo1 .map", groupname) //map formatting
      .dimension(restaurantNames)
      .group(restaurantsGroup)
      .width(700)
      .height(500)
      .center([43.733372, -79.354782])
      .zoom(11)
      .cluster(true) 
    .valueAccessor(function(kv) {
          return kv.value.count;
    })
    .locationAccessor(function(kv) {
          return [kv.value.latitude,kv.value.longitude] ;
     })
    .popup(function(kv,marker) {
          return kv.value.name + " - " + kv.value.stars + " * - "  + 
           kv.value.price_range + "$";
      });
Другие вопросы по тегам