简体   繁体   English

D3中的可重用功能

[英]Reusable functions in D3

I'm new to d3 and a pretty average javascript programmer. 我是d3的新手,并且是相当普通的javascript程序员。 I've got some code to create a circle, and a function to get the x and y co-ordinates of a point on a circle: 我有一些代码可以创建一个圆,还有一个函数可以获取圆上某个点的x和y坐标:

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};
}

It works. 有用。 But I feel like continuing with this approach will make my code a messy grab bag of global functions, and that I should be able to make it object-oriented, so rather than calling: 但是我觉得继续使用这种方法会使我的代码成为混乱的全局函数包,而且我应该能够使其面向对象,因此不必调用:

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

I can instead call: 我可以打电话给:

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

But this would involve me either attaching a pointAt function to a d3 object somehow, or creating my own Circle object that has a pointAt function, and wraps a d3 object. 但这会涉及到我要么以某种方式将pointAt函数附加到d3对象,要么创建我自己的具有pointAt函数的Circle对象并包装d3对象。 Is either of these a good idea? 这些都是好主意吗?

There's other points where I feel like I'd want something similar - kind of like I want to be mapping 'objects' to documents, as opposed to plain old data to documents. 在其他方面,我觉得我想要类似的东西-有点像我想将“对象”映射到文档,而不是将普通的旧数据映射到文档。 Is this a common requirement, or am I missing something conceptually? 这是一个普遍的要求,还是我在概念上缺少一些东西?

What's the best way to approach my pointOnCircle issue that I'm having above? 解决pointOnCircle遇到的pointOnCircle问题的最佳方法是什么?

Most of the d3 examples are small, self-contained, and written in one single script. d3的大多数示例都是小型的,独立的并且用一个脚本编写。 Are there any examples showing how to build something with more reusable functions? 是否有任何示例说明如何构建具有更多可重用功能的产品?

You can follow d3.js style of functional programming as demonstrated below 您可以遵循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;
}

This is a typical example of functional programming. 这是函数式编程的典型示例。 The main object is _circle function is obtained by calling innerCircle . 主要对象是_circle函数,是通过调用innerCircle获得的。 _circle draws a circle to an svg according to its set attributes ( current_attr , current_style ). _circle根据其设置的属性( current_attrcurrent_style )向svg 绘制一个圆。 To draw a circle to an svg, you can do it d3.js way: 要在svg上画一个圆,可以使用d3.js方式:

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

The _circle function has 3 defined methods, attr , style and pointAt . _circle函数具有3个定义的方法, attrstylepointAt attr and style are getter/setter functions, if you call them without arguments they will return the current value (getter), and if called with an argument, they will set the current value to it. attrstyle是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',
});

You can also call your pointAt function similarly. 您也可以类似地调用pointAt函数。

new_circle.pointAt(Math.PI);

One last caveat to this programming style is the return _circle; 这种编程风格的最后一个警告是return _circle; statement at the end of all setter functions, which allows chaining. 所有setter函数末尾的语句,允许链接。 So, your example can be reproduced by: 因此,您的示例可以通过以下方式重现:

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

svg.call(new_circle);

Hope this helps. 希望这可以帮助。 Let me know of any unclear points. 让我知道任何不清楚的地方。

I hope this helps. 我希望这有帮助。

 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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM