2014-03-13 40 views
3

我正在使用D3和D3.geo.projection創建一個相當簡單的世界全球接口,以創建一個帶有數據點的旋轉式球體。如何確定某個點是否隱藏在投影中?

一切正常(即點「黯然失色」,當他們離開旋轉地平線後面),當我剛剛與圈中繪製點:

svg.append("g") 
    .attr("class","points") 
    .selectAll("text") 
    .data(places.features) 
    .enter() 

    //for circle-point------------------------------ 
    .append("path") 
    .attr("d", path.pointRadius(function(d) { 
     if (d.properties) 
     return 3+(4*d.properties.scalerank); 
        })) 
    .attr("d", path) 

    .attr("class", "point") 
    .on("click",pointClick) 
; 

但現在我想要繪製的符號,而不是圈:

svg.append("g") 
    .attr("class","points") 
    .selectAll("text") 
    .data(places.features) 
    .enter() 
    //for image------------------------------------- 
    .append("image") 
    .attr("xlink:href", "img/x_symbol.png") 
    .attr("x", -12) 
    .attr("y", -12) 
    .attr("width", 24) 
    .attr("height", 24) 
    .attr("transform", function(d) { 
     return "translate(" + projection([ 
      d.properties.longitude, 
      d.properties.latitude 
     ]) + ")" 
     }) 

    .attr("class", "point") 
    .on("click",pointClick) 
; 

雖然這部作品,並在地球上的正確的地方符號情節,當他們換到地球的背面,他們堅持,即使。 如果我有辦法確定它們是否被重疊,我可以使用可見性屬性隱藏它們,但是我沒有在d3.geo.projection中看到這樣做的方法。有任何想法嗎?

+0

不一定與你的問題,但也許會刺激你創建一個小提琴......我注意到你正在爲d的屬性使得兩個賦值你的圈子點......是隻是一個複製/粘貼問題或你的原始代碼? – FernOfTheAndes

+0

啊,是的,@FernOfTheAndes,這顯然是一個多餘的線。我認爲自從我設置'pointRadius'屬性後,我仍然不得不調用'.attr(「d」,path)'。省略該行對點樣式呈現沒有影響。 我不確定我是否可以將相關部分提取到小提琴中。它依賴於兩個數據JSON和一些CSS。 –

+1

@mbostock,也許你可以點亮一些光線?我可以使用.png圖像作爲d3.geo.orthographic投影上的點嗎? –

回答

3

好的,通過計算投影中心和問題點之間的大圓距離,我至少可以模擬隱藏在地球背後的圖像。如果距離小於π/ 2時,點會超越地平線:

 .attr("opacity", function(d) { 
      var geoangle = d3.geo.distance(
        d.geometry.coordinates, 
        [ 
         -projection.rotate()[0], 
         projection.rotate()[1] 
        ]); 
      if (geoangle > 1.57079632679490) 
      { 
       return "0"; 
      } else { 
       return "1.0"; 
      } 
     }) 

我敢肯定,我可以褪色出來,他們的做法邊緣,禁用點擊等得到位票友但現在我可以繼續...

0

我知道這是一個老問題,但想添加一個新的解決方案。 您可以使用projection.stream過濾,解析並返回投影的x,y(以像素爲單位)。此方法也適用於濾除當前(縮放)範圍之外的點。

注意這將過濾(剪輯)在當前投影下不可見的所有點。如果您確實想保留所有點,請添加另一個循環來比較兩個數組。但是,在我使用反應性屬性的情況下,這很有效。

let newStream = [] 
let stream = youCurrentProjection.stream({ 
    point: function (x, y) { 
    newStream.push([x, y]) 
    } 
}) 

arrayOfPoints.forEach(point => { 
    stream.point(point.x, point.y) 
}) 

或建立一個封閉傳遞指數

let streamWrapper = function (x, y, index) { 
    let stream = youCurrentProjection.stream({ 
    point: function (x, y) { 
     arrayOfPoints[index].isVisible = true 
    } 
    }) 
    stream.point(x, y) 
} 

arrayOfPoints.forEach((point, index) => { 
    streamWrapper(point.x, point.y, index) 
}) 
+0

這是一個很好的解決方案,但它是否佔據投影區域內的點數,但超出了地平線的範圍? (我在問,我真的不知道答案) –

+0

'在投影區域內,但超出了地球的視野?',不知道我是否理解正確。但是這種方法肯定會過濾掉應該看不見的點,但是「投影(點)」會產生有效的x,y像素(點在地球的'黑暗'一側)。 – KuN

相關問題