2015-02-24 30 views
2

我是新來的D3和一個漂亮的平均JavaScript程序員。我有一些代碼來創建一個圈子,一個函數來獲取一個圓上一個點的X和Y座標:D3中的可重用函數

var innerCircle = svg.append('circle') 
    .attr({ 
    cx: 100, 
    cy: 100, 
    r: 50, 
    'stroke': 'white', 
    'fill': 'transparent', 
    }); 

var pointOnCircle = function(circle, radians){ 
    var cx = parseInt(circle.attr('cx')); 
    var cy = parseInt(circle.attr('cy')); 
    var r = parseInt(circle.attr('r')); 
    var x = cx + Math.sin(radians) * r; 
    var y = cy + Math.cos(radians) * r; 
    return {x: x, y: y}; 
} 

它的工作原理。但我覺得這種做法繼續將讓我的代碼的全局函數一片狼藉摸彩袋,那我應該能夠使它面向對象的,因此而不是調用:

var point = pointOnCircle(circle, Math.PI); 

我可以改爲調用:

var point = circle.pointAt(Math.PI); 

但是,這將涉及我或者附加pointAt功能到D3物體以某種方式,或者創建具有pointAt功能,幷包裝D3對象我自己Circle對象。這是個好主意嗎?

還有其他一些問題,我覺得我想要類似的東西 - 有點像我想將「對象」映射到文檔,而不是將普通的舊數據映射到文檔。這是一個共同的要求,還是我在概念上錯過了一些東西?

什麼是最好的方式來處理我上面的pointOnCircle問題?

大多數d3示例都是小型的,自包含的,並且用一個腳本編寫。是否有任何示例顯示如何構建具有更多可重用功能的內容?

回答

3

您可以按照函數式編程的d3.js風格表現出以下

function innerCircle() { 
    var current_attr, current_style, circle_elem; 

    var _circle = function (svg) { 
     circle_elem = svg.append('circle') 
      .attr(current_attr) 
      .attr(current_style); 

     return circle_elem; 
    } 

    _circle.pointAt = function (randians) { 
     if(! circle_elem)  //If the circle is not drawn yet. 
      return {x: -1, y: -1}; 

     var cx = parseInt(circle_elem.attr('cx')); 
     var cy = parseInt(circle_elem.attr('cy')); 
     var r = parseInt(circle_elem.attr('r')); 
     var x = cx + Math.sin(radians) * r; 
     var y = cy + Math.cos(radians) * r; 
     return {x: x, y: y}; 
    } 

    _circle.attr = function(attr_val){ 
     if(! arguments.length) 
      return current_attr; 

     current_attr = attr_val; 
     return _circle; 
    } 

    _circle.style = function(style_val){ 
     if(arguments.length == 1) 
      return current_style; 

     current_style = style_val; 
     return _circle; 
    } 

    return _circle; 
} 

這是函數式編程的一個典型例子。主要目標是通過調用innerCircle獲得函數_circle_circle根據其設定的屬性(current_attr,current_style)將一個圓圈繪製爲。要繪製圓到SVG,你可以做到這一點d3.js方式:

var new_circle = innerCircle(); 
svg.call(new_circle); 

_circle功能有3種定義的方法,attrstylepointAtattrstyle是getter/setter函數,如果您在沒有參數的情況下調用它們,它們將返回當前值(getter),如果使用參數調用它們,它們會將當前值設置爲它。

new_circle.style(); //get the current style 

//set attributes 
new_circle.attr({ 
    cx: 100, 
    cy: 100, 
    r: 50, 
    'stroke': 'white', 
    'fill': 'transparent', 
}); 

你也可以用類似的方式調用你的pointAt函數。

new_circle.pointAt(Math.PI); 

最後一個警告這種編程風格是在所有setter函數結束,這使得鏈接的return _circle;聲明。所以,你的例子可以複製:

var new_circle = innerCircle() 
    .attr({ 
    cx: 100, 
    cy: 100, 
    r: 50,  
    }) 
    .style({ 
    'stroke': 'white', 
    'fill': 'transparent', 
    }); 

svg.call(new_circle); 

希望這會有所幫助。讓我知道任何不清楚的問題。

+0

謝謝!就是我以後的樣子。然後就組織代碼而言,我假設你通常會將每個包含外部函數放在一個新的.js文件中? – 2015-02-24 10:32:33

+0

你可以做到這一點。另外,如果你把它放到一個大的項目中,你應該把你的函數放在單獨的名字空間中。 – ahmohamed 2015-02-24 10:35:10

1

我希望這有助於。

var myProgram = {}; 
 
myProgram.circleModule = (function() { 
 
    var innerCircle = d3.select("#svg").append('circle') 
 
    .attr({ 
 
     cx: 100, 
 
     cy: 100, 
 
     r: 50, 
 
     'stroke': 'black', 
 
     'fill': 'red', 
 
    }); 
 

 
    var pointOnCircle = function(circle, radians) { 
 
    var cx = parseInt(circle.attr('cx')); 
 
    var cy = parseInt(circle.attr('cy')); 
 
    var r = parseInt(circle.attr('r')); 
 
    var x = cx + Math.sin(radians) * r; 
 
    var y = cy + Math.cos(radians) * r; 
 
    return { 
 
     x: x, 
 
     y: y 
 
    }; 
 
    } 
 

 
    return { 
 
    circle: innerCircle, 
 
    pointOnCircle: pointOnCircle 
 
    } 
 
})();
<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
 
    <title>Untitled Document</title> 
 
    <script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> 
 
</head> 
 

 
<body> 
 
    <svg id="svg" width="200" height="200"> 
 

 
    </svg>

+0

一個更簡單的例子,更具體地涉及我給出的答案將是非常棒的。 – 2015-02-24 08:00:59

+0

(對不起,我給的例子,不是我給的答案) – 2015-02-24 09:11:41

+0

我已經更新了答案,請檢查 – Rudra 2015-02-24 10:13:05