最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Create custom a d3 generator - Stack Overflow

programmeradmin1浏览0评论

So I can create an area generator:

d3.svg.area()

...or a line generator:

d3.svg.line()

But is it possible to create your own generator, such as a circle generator?:

d3.svg.circle()

I'd just like to be able to use this clear syntax:

// don't know if it's possible to do this...
svg.append('path').datum(data).attr({
  d: circleGenerator
})

Rather than create a circle in-place using the weird (at least to me) vg.selectAll('circle').data(data).enter().append('circle').attr() method chain:

// the correct but messy way to do it...
svg.selectAll('circle').data(data).enter().append('circle').attr({
  cx: function(d){ return d.x },
  cy: function(d){ return d.y },
  r: 3,
  transform: 'translate(100,200)'
});

I'd like to be able to extract all of this logic into a generator, and pass it information via datum

So I can create an area generator:

d3.svg.area()

...or a line generator:

d3.svg.line()

But is it possible to create your own generator, such as a circle generator?:

d3.svg.circle()

I'd just like to be able to use this clear syntax:

// don't know if it's possible to do this...
svg.append('path').datum(data).attr({
  d: circleGenerator
})

Rather than create a circle in-place using the weird (at least to me) vg.selectAll('circle').data(data).enter().append('circle').attr() method chain:

// the correct but messy way to do it...
svg.selectAll('circle').data(data).enter().append('circle').attr({
  cx: function(d){ return d.x },
  cy: function(d){ return d.y },
  r: 3,
  transform: 'translate(100,200)'
});

I'd like to be able to extract all of this logic into a generator, and pass it information via datum

Share Improve this question asked Nov 20, 2014 at 14:37 StarkersStarkers 10.6k22 gold badges101 silver badges166 bronze badges 1
  • Yes, you can create your own generator. Chances are that any shapes you may want are covered already by the superformula generator already though. – Lars Kotthoff Commented Nov 20, 2014 at 16:07
Add a ment  | 

1 Answer 1

Reset to default 8

This is certainly possible, you would need to create this generator from scratch, i.e.:

function circleGen() {
  //set defaults
  var r = function(d) { return d.radius; },
      x = function(d) { return d.x; },
      y = function(d) { return d.y; };

  //returned function to generate circle path
  function circle(d) {
    var cx = d3.functor(x).call(this, d),
        cy = d3.functor(y).call(this, d),
        myr = d3.functor(r).call(this, d);

    return "M" + cx + "," + cy + " " +
           "m" + -myr + ", 0 " +
           "a" + myr + "," + myr + " 0 1,0 " + myr*2  + ",0 " +
           "a" + myr + "," + myr + " 0 1,0 " + -myr*2 + ",0Z";
  }

  //getter-setter methods
  circle.r = function(value) {
    if (!arguments.length) return r; r = value; return circle;
  };  
  circle.x = function(value) {
    if (!arguments.length) return x; x = value; return circle;
  };  
  circle.y = function(value) {
    if (!arguments.length) return y; y = value; return circle;
  };

  return circle;
}

Then, it can be used as you describe:

var myC = circleGen()
   .x(function(d) { return d.x; })
   .y(function(d) { return d.y; })
   .r(function(d) { return d.r; });

var data = [
  {x: 150, y: 100, r: 10, fill: "green"},
  {x: 200, y: 150, r: 5, fill: "red"},
  {x: 100, y: 250, r: 25, fill: "blue"}
];

svg.selectAll("path.circle")
    .data(data)
  .enter().append("path")
    .attr("class", "circle")
    .attr("d", myC)
    .style("fill", function(d) { return d.fill; });

Full example: http://bl.ocks/jsl6906/cb75852db532cee284ed

发布评论

评论列表(0)

  1. 暂无评论