Интеграция 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), если это те свойства, которые вы передаете?

Другие вопросы по тегам