2013-06-29 88 views
2

我正在學習Clojurescript如何運作,試圖使用d3.js. JSON結構得出一些與電網工作突變我正在使用strokes訪問d3。在Clojurescript

的JSON看起來是這樣的:

[[{"players":{"0":{"rep":0},"1":{"rep":0}}},{"players":{"0":{"rep":0},"1":{"rep":0}}}, 
    {"players":{"0":{"rep":0},"1":{"rep":0}}},{"players":{"0":{"rep":0},"1":{"rep":0}}}], 
[{"players":{"0":{"rep":0},"1":{"rep":0}}},{"players":{"0":{"rep":0},"1":{"rep":0}}}, 
    {"players":{"0":{"rep":0},"1":{"rep":0}}},{"players":{"0":{"rep":0},"1":{"rep":0}}}], 
[{"players":{"0":{"rep":0},"1":{"rep":0}}},{"players":{"0":{"rep":0},"1":{"rep":0}}}, 
    {"players":{"0":{"rep":0},"1":{"rep":0}}},{"players":{"0":{"rep":0},"1":{"rep":0}}}], 
[{"players":{"0":{"rep":0},"1":{"rep":0}}},{"players":{"0":{"rep":0},"1":{"rep":0}}}, 
    {"players":{"0":{"rep":0},"1":{"rep":0}}},{"players":{"0":{"rep":0},"1":{"rep":0}}}]] 

它代表了一個4×4的網格。我試圖給單元格添加值,例如高度,寬度,x和y座標,這樣只是將數據傳遞給d3來繪製的簡單情況。

例如,它會是這個樣子:

[[{"width":32,"height":32,"x":0,"y":0,"value":{"players":{"0":{"rep":0},"1":{"rep":0}}}}, 
    {"width":32,"height":32,"x":32,"y":0,"value":{"players":{"0":{"rep":0},"1":{"rep":0}}}},... 

通常我會在映射具有轉換功能的結構,細胞從當前值轉換成一種新的形式,但這種做法只是沒有按似乎沒有工作。我試過map-indexed: (map-indexed #(doto %2 (aset "width" %1)) row),但這似乎沒有正確轉換值。這很可能是我正在訪問或設置值不正確。

代碼的當前迭代看起來是這樣的:

(defn board->grid [grid-width grid-height board square] 
    (let [x-length (count board) 
     y-length (count (first board)) 
     same (min (/ grid-width x-length) (/ grid-height y-length)) 
     grid-item-width (if square same (/ grid-width x-length)) 
     grid-item-height (if square same (/ grid-height y-length)) 
     start-x (/ grid-item-width 2) 
     start-y (/ grid-item-height 2) 
     values (array) 
     grid (array) 
     data (js->clj board :keywordize-keys true)] 
     (doseq [x (range x-length) 
       y (range y-length)] 
      (let [current-cell (aget data y x)] 
      (.log js/console (apply str (aset (aget data y x) "a" "b"))) 
      (.push grid (aget data y x)))) 
     (.text ($ :#status) grid))) 

任何幫助,將不勝感激!或者更好的是,更好的方法的建議,我不禁感到我正在做這個有點錯誤!

回答

5

根據經驗,用Clojure和clojurescript與可變性工作的基本規則是「不」。 JS數組和對象不實現大多數函數依賴於他們工作的協議。例如,普通的js數組不能被seqable!只有在需要與其他庫進行交互時,才能使用不可變數據結構執行大部分工作,並將其轉換爲可變等效項。

還有一些附加的功能,這是陣列特異性:into-arrayto-arrayagetasetamapareducealength。 (見本cheat sheet)。

有,如果你想堅持使用可變數據結構,您可以在goog.arraygoog.object,或goog.structs找到有用的也不少closure library功能。 (請記住,clojurescript包括谷歌封閉庫!)

您也可以在任何地方使用這種形式:

(defn amap2d [arr f] 
    (doseq [x (range (alength arr)) 
      y (range (alength (aget A x))) 
     :let [cell (aget A y x)]] 
    (f x y cell))) 

但我認爲你會更快樂做js->clj,對數據的工作,然後clj->js你把它傳遞給D3權利之前。

+0

謝謝!我會做你的建議,感覺最自然! – toofarsideways

+0

更多地研究「筆畫」的功能。它看起來像使用['mrhyde'](https://github.com/dribnet/mrhyde)庫,它允許通過javascript代碼更容易地使用clj數據結構。你甚至可能不需要最後的'js-> clj'步驟! –

+0

我實際上在'strokes'和'c2'之間反彈,而我目前主要使用'c2',因爲它通過'bind!'提供了非常好的功能...... – toofarsideways

1

我不熟悉clojurescript;一些建議,但:

格式化數組的數組與座標對象的平面陣列是不是太硬香草的javascript:

var grid = []; 
board.forEach(function(row, y){ 
    row.forEach(function(d, x){ 
    d.y = y; d.x = x; grid.push(d); }); }); 

要顯示板,你可能想使用這樣的事情:

svg.selectAll("rect") 
    .data(grid).enter().append("svg:rect") 
    .attr("x", function(d){ return xScale(d.x); }) 
    .attr("y", function(d){ return yScale(d.y); }) 
    .attr("height", rectHeight) 
    .attr("width", rectWidth) 

注意,方形的實際位置不存儲在對象,這樣更容易跟蹤與規模:

xScale = d3.scale.linear() 
    .domain(d3.extent(grid.map(function(d){ return d.x; }). 
    .range(0, svgWidth); 
4

我看到你在data使用agetdata是ClojureScript數據結構。 aget僅用於處理類似數組的JavaScript對象。

+0

謝謝你指出:)...順便說一句大衛,愛你的工作! – toofarsideways