Всплывающее окно маркера листовки 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 + "$";
});