2015-02-24 2 views
2

Я новичок в d3 и довольно средний программист javascript. У меня есть некоторый код, чтобы создать круг, и функцию, чтобы получить й и у координаты точки на окружности:Многоразовые функции в 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 как-то, или создать свой собственный Circle объект, который имеет pointAt функцию, и оборачивает объект d3. Является ли это хорошей идеей?

Есть другие моменты, когда я чувствую, что хочу что-то подобное - вроде как я хочу отображать «объекты» в документы, а не простые старые данные в документы. Является ли это общим требованием, или я чего-то не понимаю концептуально?

Каков наилучший способ приблизиться к моему вопросу 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; 
} 

Это типичный пример функционального программирования. Основной объект _circle Функция получена по телефону innerCircle. _circleрисует круг в svg в соответствии с его установленными атрибутами (current_attr, current_style). Для того, чтобы нарисовать круг на SVG, вы можете сделать это d3.js путь:

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

_circle функция имеет 3 определенные методы, attr, style и pointAt. attr и style являются функциями 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); 

последнее предостережение к этому стилю программирования является return _circle; заявления в конце всех функций инкубационных, что позволяет цепочку.Итак, ваш пример может быть воспроизведен:

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

svg.call(new_circle); 

Надеюсь, это поможет. Дайте мне знать о каких-либо неясных моментах.

+0

Спасибо! Только то, что мне нужно. И затем, с точки зрения организации вашего кода, я предполагаю, что вы обычно помещаете каждую внешнюю содержащую функцию в новый .js-файл? –

+0

Вы можете это сделать. Кроме того, если вы включаете это в большой проект, вы должны поместить свои функции в отдельное пространство имен. – ahmohamed

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

Простой пример, связанный более конкретно с ответом, который я дал, был бы замечательным. –

+0

(извините, к примеру, я дал, а не ответ, который я дал) –

+0

Я обновил ответ, пожалуйста, проверьте – Rudra