因此,我正在嘗試爲使用d3.js,polymaps和Coffeescript的項目做一些地圖標記聚類。d3.js中SVG元素的聚類產生意想不到的結果
我計算基於所述基礎數據的簇,然後羣集陣列傳遞到D3爲。數據(簇狀物)
簇的放置似乎是確定。初始縮放級別上的聚類似乎沒問題,根據我的知識是100%準確的。當我改變縮放級別時,乍看起來一切似乎都很好,但是當我將鼠標懸停在圈子上時,說明似乎與它們的位置以及路線之前的位置相匹配,看起來並不匹配現在。
我在http://bl.ocks.org/3161013上準備了一個包含完整代碼的例子。
我看到兩個主要的失敗點:集羣和更新SVG。
聚類的代碼相當簡單,並基於Mark Tuupola,但在coffeescript而不是php。
cluster: (elements, distance) ->
currentElements = elements.slice(0)
pixelDistance = @pixelDistance()
distLat = distance * pixelDistance.lat
distLon = distance * pixelDistance.lon
clustered = []
while currentElements.length > 0
stop = currentElements.shift()
cluster = []
cluster.push stop
i = 0
while i < currentElements.length
if Math.abs(currentElements[i].lat - stop.lat) < distLat and Math.abs(currentElements[i].lon - stop.lon) < distLon
aStop = currentElements.splice i,1
cluster.push aStop[0]
i--
i++
clustered.push cluster
clustered
SVG更新代碼看起來像是相當直接的d3代碼。當地圖移動時,這個更新方法被調用。如果縮放已經改變,或者預聚集的數據已經改變,我們重新聚類和佈局,否則我們只是翻譯現有的點。
update: ->
if not @stops
@stops = []
if not @prevNumStops
@prevNumStops = 0
if not @prevZoom
@prevZoom = 0
if @zoomLevel() != @prevZoom or @prevNumStops != @stops.length
@prevZoom = @zoomLevel()
@prevNumStops = @stops.length
start = new Date()
@clusters = @cluster(@stops,10)
console.log @clusters
console.log "clustering: " + ((new Date()) - start)
start = new Date()
marker = @selector.selectAll("g").data(@clusters)
marker.enter().append("g")
.append("circle")
.attr("class", "stop no-tip")
marker.exit().remove()
@selector.selectAll("g").selectAll("circle")
.attr('r', (cluster) -> if cluster.length > 1 then 5 else 3.5)
.attr("text", (cluster) -> "<ul>" + ((("<li>" + route + "</li>") for route in stop.routes).join("") for stop in cluster).join("") + "</ul>")
@selector.selectAll("g").attr("transform", (cluster) =>
@transform cluster[0]
)
我覺得這裏可能有些簡單的東西我很想念,但是我對d3還是比較新的。