Интеграция Clojurescript с картами данных устанавливает ширину и высоту SVG 0
Мы рендерим Datamaps из clojurescript, и у него странное поведение. Карты данных имеют элемент, передаваемый из clojurescript, но визуализируются с width и height = 0.
<div id="cash-balance-globe" class="cash-balance-globe tile-date-info" style="width: 361px;height: 187px;">
<svg width="0" data-width="0" class="datamap" height="0" style="overflow: hidden;"><g id="" class="datamaps-subunits">
Код, который передается в элементе:
(defn cash-balance-globe
^{:externs [[globe.render] [globe.highlightBubble]]}
[cash-balance-by-country selected-country-atom]
(let [globe-data (doall (map #(assoc %
:name (get % "country")
:value (get % "balance")) cash-balance-by-country))]
(letfn [(reagent-render [] (let [country-selected? (not (nil? @selected-country-atom))
selected-country-cash-balance (first (filter #(= (:name %) @selected-country-atom) globe-data))]
[:div
(if country-selected?
[selected-country-breakdown-table selected-country-cash-balance]
[:div "Select country to see detail"])
[:div {:id "cash-balance-globe"
:class "cash-balance-globe tile-date-info"
:style {:width "360px" :height "187px"}}]]))
(component-did-mount [] (let [set-selected-country (fn [x]
(reset! selected-country-atom
(get (js->clj x) "name")))
globe-container (js/document.getElementById "cash-balance-globe")]
(.. js/globe
(render globe-container (clj->js globe-data) set-selected-country popup-template #js [7 20]))
(when (not (nil? @selected-country-atom))
(.. js/globe
(highlightBubble @selected-country-atom globe-container)))
))]
(r/create-class
{:reagent-render reagent-render
:component-did-mount component-did-mount}))))
Вызываемый здесь globe.js имеет следующую функцию рендеринга:
ns.render = function(container, countriesData, onCountrySelect, popupText, radiusRange) {
var values = function(d) { return d.value; };
var radiusScale = d3.scale.linear()
.domain([0,d3.max(countriesData, values)])
.range(radiusRange);
var globalMap = new Datamap({
element: container,
scope:'world',
geographyConfig: {
borderColor:'#818181',
popupOnHover: false,
highlightOnHover: false
},
fills: countryFills()
});
Мы застряли в этом на несколько дней. Работает, когда страница перерисовывается, только в первый раз не работает.
Кроме того, функция рендера получает элемент div с правильной шириной и высотой, мы проверили console.log
2 ответа
Так что я наконец нашел ответ на это. Проблема заключалась в том, что значения по умолчанию в картах данных не вызывались из вызова Clojurescript. Поэтому нам пришлось сделать вызов по умолчанию из самой функции рендеринга как:
ns.render = function(container, countriesData, onCountrySelect, popupText, radiusRange) {
var values = function(d) { return d.value; };
var radiusScale = d3.scale.linear()
.domain([0,d3.max(countriesData, values)])
.range(radiusRange);
var height = 168;
var width = 360;
var globalMap = new Datamap({
element: container,
scope:'world',
height: height,
width: width,
"data-width": width,
setProjection: function() {
var projection = d3.geo.equirectangular()
.scale(width / 2 / 3.1415926535)
.translate([width / 2, height / 2]);
var path = d3.geo.path().projection( projection );
return {path: path, projection: projection};
},
fills: countryFills()
});
Можете ли вы объяснить лучше, где эта функция render
идет от.
глобус-контейнер (js/document.getElementById "cash-balance-globe")
Этот глобальный контейнер не может быть передан, чтобы реагировать (будь то реагент или любая реагирующая оболочка) на рендеринг, если это то, что вы делаете. Если этот элемент dom фактически отображает svg, вам нужно предоставить информацию о том, что возвращается в (clj->js globe-data)
, если это те свойства, которые вы передаете?