D3 メモ [SVG基礎編]

基本

SVGでグラフィックを描画する場合には、まずHTMLにsvg要素を追加して
描きたいシェイプを追加していく感じ。

function draw(json) {
  var w = 500,
      h = 500;

  var svg = d3.select('#container')
              .append('svg:svg')
              .attr('width', w)
              .attr('height', h);

  svg.append('svg:circle')
     .attr('cx', 50)
     .attr('cy', h/2)
     .attr('r', 30)
     .attr('fill', '#333');

  svg.append('svg:rect')
     .attr('x', 100)
     .attr('y', h/2 - 15)
     .attr('width', 50)
     .attr('height', 30)
     .attr('rx', 5)   // x方向の角丸
     .attr('ry', 5);  // y方向の角丸

  svg.append('svg:ellipse')
     .attr('cx', 190)
     .attr('cy', h/2)
     .attr('rx', 30)  // x方向の半径
     .attr('ry', 20); // y方向の半径

  svg.append('svg:line')
     .attr('x1', 10)
     .attr('y1', h/2 + 50)
     .attr('x2', 490)
     .attr('y2', h/2 + 50)
     .attr('stroke', '#333');

  svg.append('svg:polyline')
     .attr('points', function() {
       var points = [],
           baseY = 50;

       for(var x = 10; x <= 300; x+=10) {
         var point = '';
         if(x / 10 % 2) {
           point = x + ',' + baseY;
         } else {
           point = x + ',' + (baseY + 20);
         }
         points.push(point);
       }
       return points.join(' ');
     })
     .attr('fill', 'none')
     .attr('stroke', '#333');

  svg.append('svg:polygon')
     .attr('points', '10,100 10,130 50,150, 90,130 90,100')
     .attr('fill', 'none')
     .attr('stroke', '#333');

  svg.append('svg:path')
     .attr('d', 'M10,160 L10,190 L50,190')
     .attr('fill', 'none')
     .attr('stroke', '#333');
}


データをバインドして表示してみる。

function init() {
  d3.json('data/videos.json', draw);
}

function initData(json) {
  return _.map(json.data.items, function(item) {
    return {
      title: item.title,
      fav: item.favoriteCount,
      view: item.viewCount,
      uploaded: item.uploaded
    };
  });
}

function draw(json) {
  var data = initData(json),
      canvW = 800,
      canvH = 495,
      ch = canvH/data.length,
      max, w,
      svg;

  max = d3.max(data, function(d) { return d.view; });
  w = d3.scale.linear().domain([0, max]).range([10, ch]);

  svg = d3.select('#container')
          .append('svg:svg')
          .attr('width', canvW)
          .attr('height', canvH);

  // view数で半径を決める
  svg.selectAll('circle')
     .data(data)
     .enter()
     .append('svg:circle')
     .attr('cx', '50px')
     .attr('cy', function(d, idx) {
       return idx * ch + w(max) / 2;
     })
     .attr('r', function(d) {
       return w(d.view) / 2;
     })
     .attr('fill', '#333')
     .attr('stroke', '#3b93ff')
     .attr('stroke-width', function(d) {
       return w(d.view) / 4;
     });

  // titleテキスト
  svg.selectAll('text')
     .data(data)
     .enter()
     .append('svg:text')
     .text(function(d) {
       return d.title;
     })
     .attr('x', function(d) {
        return 50 + ch;
     })
     .attr('y', function(d, idx) {
        return idx * ch + w(max) / 2 + 5;
     })
     .attr('font-size', '12px');
}