代码之家  ›  专栏  ›  技术社区  ›  Harry Stevens

D3.js插件中的链接函数

  •  3
  • Harry Stevens  · 技术社区  · 8 年前

    d3-marcon 实现 Mike Bostock's margin conventions 例如,不必写:

    var margin = {top: 10, bottom: 10, left: 10, right: 10},
        width = window.innerWidth - margin.left - margin.right,
        height = window.innerHeight - margin.top - margin.bottom,
        svg = d3.select("body").append("svg")
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
            .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    

    var setup = d3.marcon({top: 10, bottom: 10, left: 10, right: 10, width: window.innerWidth, height: window.innerHeight}),
        margin = setup.margin,
        width = setup.width,
        height = setup.height,
        svg = setup.svg;
    

    如您所见,它通过将options对象传递给 marcon() 作用如果未指定任何选项,则默认为 0 900 对于宽度, 600 对于高度,并将svg元素附加到 "body" var setup = d3.marcon()

    d3.marcon({element: ".viz"}) ,D3代码看起来像 d3.marcon().element(".viz") .

    D3代码还允许您将其他函数传递给链接函数(例如。 d3.method().chainedFunction(function(d) { return d.value; }) ),因此可以基于数据更新对象的属性。

    显然,我的插件不做这些事情。我花了几个小时研究现有的D3模块,试图弄清楚它们是如何工作的,但我什么都没做。有人能建议如何让我的代码像一个合适的D3模块一样工作吗?或者,如果做不到这一点,是一本很好的阅读教程?

    我链接到了上面的存储库,但是 here it is again here is a block 展示其工作原理。

    2 回复  |  直到 8 年前
        1
  •  3
  •   Gerardo Furtado    8 年前

    这是我的建议,基于朱在他的书中的方法

    基本上,我们用一个对象创建一个函数。。。

    function marcon() {
        var instance = {};
    }
    

    …并分别设置每个方法:

    instance.top = function(d) {
        if (!arguments.length) return top;
        top = d;
        return instance;
    };
    

    最后,使用调用渲染部分 render()

    marcon().top(10)
        .left(10)
        //etc...
        .render();
    

    这种方法的优点是,根据您的要求,它允许链接。例如,您可以这样创建SVG:

    var mySvg = marcon();
    
    mySvg.top(20)
        .left(10)
        .right(10)
        .bottom(10)
        .height(200)
        .width(200)
        .element("body")
        .render();
    

    function marcon() {
      var instance = {};
      var top = 10,
        bottom = 0,
        left = 0,
        right = 0,
        width = 900,
        height = 600,
        element = "body",
        innerWidth, innerHeight, svg;
    
      instance.top = function(d) {
        if (!arguments.length) return top;
        top = d;
        return instance;
      };
    
      instance.left = function(d) {
        if (!arguments.length) return left;
        left = d;
        return instance;
      };
    
      instance.right = function(d) {
        if (!arguments.length) return right;
        right = d;
        return instance;
      };
    
      instance.bottom = function(d) {
        if (!arguments.length) return bottom;
        bottom = d;
        return instance;
      };
    
      instance.width = function(d) {
        if (!arguments.length) return width;
        width = d;
        return instance;
      };
    
      instance.height = function(d) {
        if (!arguments.length) return height;
        height = d;
        return instance;
      };
    
      instance.element = function(d) {
        if (!arguments.length) return element;
        element = d;
        return instance;
      };
    
      instance.innerWidth = function() {
        return innerWidth;
      };
    
      instance.innerHeight = function() {
        return innerHeight;
      };
    
      instance.svg = function() {
        return svg;
      };
    
      instance.render = function() {
        innerWidth = width - left - right;
        innerHeight = height - top - bottom;
        svg = d3.select(element)
          .append("svg")
          .attr("width", innerWidth + left + right)
          .attr("height", innerHeight + top + bottom)
          .append("g")
          .attr("transform", "translate(" + left + ", " + top + ")");
      }
    
      return instance;
    }
    
    var mySvg = marcon();
    mySvg.top(20)
      .left(10)
      .right(10)
      .bottom(20)
      .height(200)
      .width(200)
      .element(".testDiv")
      .render();
    
    var rect = mySvg.svg()
      .append("rect")
      .attr("width", mySvg.innerWidth())
      .attr("height", mySvg.innerHeight())
      .style("fill", "teal")
    svg {
      background-color: tan;
    }
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <div class="testDiv"></div>

    此外,它允许默认设置。如果不设置setter,则默认为指定的值。在这里,如果我们不设置宽度,它默认为900:

    function marcon() {
      var instance = {};
      var top = 10,
        bottom = 0,
        left = 0,
        right = 0,
        width = 900,
        height = 600,
        element = "body",
        innerWidth, innerHeight, svg;
    
      instance.top = function(d) {
        if (!arguments.length) return top;
        top = d;
        return instance;
      };
    
      instance.left = function(d) {
        if (!arguments.length) return left;
        left = d;
        return instance;
      };
    
      instance.right = function(d) {
        if (!arguments.length) return right;
        right = d;
        return instance;
      };
    
      instance.bottom = function(d) {
        if (!arguments.length) return bottom;
        bottom = d;
        return instance;
      };
    
      instance.width = function(d) {
        if (!arguments.length) return width;
        width = d;
        return instance;
      };
    
      instance.height = function(d) {
        if (!arguments.length) return height;
        height = d;
        return instance;
      };
    
      instance.element = function(d) {
        if (!arguments.length) return element;
        element = d;
        return instance;
      };
    
      instance.innerWidth = function() {
        return innerWidth;
      };
    
      instance.innerHeight = function() {
        return innerHeight;
      };
    
      instance.svg = function() {
        return svg;
      };
    
      instance.render = function() {
        innerWidth = width - left - right;
        innerHeight = height - top - bottom;
        svg = d3.select(element)
          .append("svg")
          .attr("width", innerWidth + left + right)
          .attr("height", innerHeight + top + bottom)
          .append("g")
          .attr("transform", "translate(" + left + ", " + top + ")");
      }
    
      return instance;
    }
    
    var mySvg = marcon();
    mySvg.top(20)
      .left(10)
      .right(10)
      .bottom(20)
      .height(200)
      .element("body")
      .render();
    
    var rect = mySvg.svg()
      .append("rect")
      .attr("width", mySvg.innerWidth())
      .attr("height", mySvg.innerHeight())
      .style("fill", "teal")
    svg{
    }
    <<div class=“testDiv”></div>

    最后,您可以使用getter,例如:

    marcon().top();
    

    这给了你价值。这是一个演示,请查看控制台:

    function marcon() {
      var instance = {};
      var top = 10,
        bottom = 0,
        left = 0,
        right = 0,
        width = 900,
        height = 600,
        element = "body",
        innerWidth, innerHeight, svg;
    
      instance.top = function(d) {
        if (!arguments.length) return top;
        top = d;
        return instance;
      };
    
      instance.left = function(d) {
        if (!arguments.length) return left;
        left = d;
        return instance;
      };
    
      instance.right = function(d) {
        if (!arguments.length) return right;
        right = d;
        return instance;
      };
    
      instance.bottom = function(d) {
        if (!arguments.length) return bottom;
        bottom = d;
        return instance;
      };
    
      instance.width = function(d) {
        if (!arguments.length) return width;
        width = d;
        return instance;
      };
    
      instance.height = function(d) {
        if (!arguments.length) return height;
        height = d;
        return instance;
      };
    
      instance.element = function(d) {
        if (!arguments.length) return element;
        element = d;
        return instance;
      };
    
      instance.innerWidth = function() {
        return innerWidth;
      };
    
      instance.innerHeight = function() {
        return innerHeight;
      };
    
      instance.svg = function() {
        return svg;
      };
    
      instance.render = function() {
        innerWidth = width - left - right;
        innerHeight = height - top - bottom;
        svg = d3.select(element)
          .append("svg")
          .attr("width", innerWidth + left + right)
          .attr("height", innerHeight + top + bottom)
          .append("g")
          .attr("transform", "translate(" + left + ", " + top + ")");
      }
    
      return instance;
    }
    
    var mySvg = marcon();
    mySvg.top(20)
      .left(10)
      .right(10)
      .bottom(20)
      .height(200)
      .width(200)
      .element("body")
      .render();
    
    var rect = mySvg.svg()
      .append("rect")
      .attr("width", mySvg.innerWidth())
      .attr("height", mySvg.innerHeight())
      .style("fill", "teal");
      
    console.log("The height is " + mySvg.height())
    svg{
    背景色:棕褐色;
    }
    <<div class=“testDiv”></div>
        2
  •  2
  •   Mark    8 年前

    tutorial d3 。将这些想法与您的代码结合起来,看起来像这样:

    <!DOCTYPE html>
    <html>
    
    <head>
      <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
    </head>
    
    <body>
      <script>
        function marcon() {
          
          var top = 0,
          	bottom = 0,
          	left = 0,
          	right = 0,
          	width = 900,
          	height = 600,
          	svg;
    
          function self(selection) {
            
        		var w = width - left - right,
        		    h = height - top - bottom;
        		
        		svg = selection.append("svg")
        		  .attr("width", width + left + right)
        			.attr("height", height + top + bottom)
        			.append("g")
        			.attr("transform", "translate(" + left + ", " + top + ")");
        	}
    
          self.top = function(value) {
            if (!arguments.length) return top;
            top = value;
            return self;
          };
    
          self.bottom = function(value) {
            if (!arguments.length) return bottom;
            bottom = value;
            return self;
          };
          
          self.left = function(value) {
            if (!arguments.length) return left;
            left = value;
            return self;
          };
          
          self.right = function(value) {
            if (!arguments.length) return right;
            right = value;
            return self;
          };
          
          self.width = function(value) {
            if (!arguments.length) return width;
            width = value;
            return self;
          };
          
          self.height = function(value) {
            if (!arguments.length) return height;
            height = value;
            return self;
          };
          
          self.svg = function(value){
            if (!arguments.length) return svg;
            svg = value;
            return self;
          }
    
    
          return self;
        }
        
        var m = marcon()
          .width(100)
          .height(100)
          .top(50)
          .left(50);
        
        d3.select('body')
          .call(m);
          
        m.svg()
          .append("text")
          .text("Hi Mom!");
        
      </script>
    </body>
    
    </html>