D3.js > D3-3Dで軸を描画する方法

更新日 2019-10-22
広告
D3.jsで3次元グラフを書くときに、軸を描画する方法を紹介します。 (まずはこちらの記事をご覧ください)

ちなみに、アングルが0(全く回転させない)状態だと、2次元(x軸とy軸)を直角に見る視点になります。 このとき、z軸は奥行きとなります。プラスだと奥で、マイナスだと手前です。

ソースコードは以下です。 頭で考えると複雑なので、変数の値を修正して、グラフがどう変化するかを確かめていくと、どの変数がどういう意味を持つのかが視覚的に理解しやすいと思います。

var origin  = [400, 200],
    axisOrigin  = [400, 200],
    alpha = 0.3,
    beta = 3,
    data = [],
    max = 4,
    min = -max,
    rad = Math.PI/180;
var xLine = [], yLine = [], zLine = [];
var scale = 30;
var svg   = d3.select('svg');
var color = d3.scaleOrdinal(d3.schemeCategory10);
var rn    = function(min, max){ return Math.round(d3.randomUniform(min, max + 1)()); };

// line data
d3.range(-4, 2, 2).forEach(function(i){
    var o = [
        [ 3,      0      , i],
        [ 2, rn(min, max), i],
        [ 1, rn(min, max), i],
        [ 0, rn(min, max), i],
        [-1, rn(min, max), i],
        [-2, rn(min, max), i],
        [-3,      0      , i]
    ];
    data.push(o);
});

var _3d = d3._3d()
    .scale(scale)
    .origin(origin)
    .shape('LINE_STRIP')
    .rotateX(alpha)
    .rotateY(beta);

var data3D = _3d(data);

processLineData(data);

function processLineData(data){
    var linesStrip = svg.selectAll('path').data(data);
    linesStrip
        .enter()
        .append('path')
        .merge(linesStrip)
        .attr('fill', 'none')
        .attr('stroke', function(d, i){ return color(i); })
        .attr('stroke-width', 2)
        .sort(function(a, b){ return b[0].rotated.z - a[0].rotated.z; })
        .attr('d', _3d.draw);
    
    linesStrip.exit().remove();
};

// x軸を表すオブジェクト生成
var xScale3d = d3._3d()
    .shape('LINE_STRIP')
    .origin(axisOrigin)
    .rotateX(alpha)
    .rotateY(beta)
    .scale(scale);

// x軸のデータを作成(-5から5までのx軸)
d3.range(-5, 5, 1).forEach(function(d){ xLine.push([d, 0, 0]); });
  
var xScaleData = xScale3d([xLine]);
processXScaleData(xScaleData);

// x軸の描画
function processXScaleData(data){
    var xScale = svg.selectAll('path.xScale').data(data);

    xScale
    .enter()
    .append('path')
    .attr('class', '_3d xScale')
    .merge(xScale)
    .attr('stroke', 'blue')
    .attr('stroke-width', .5)
    .attr('d', xScale3d.draw);
  
    xScale.exit().remove();
};


// y axis
var yScale3d = d3._3d()
    .shape('LINE_STRIP')
    .origin(origin)
    .rotateX(alpha)
    .rotateY(beta)
    .scale(scale);

d3.range(-10, 10, 1).forEach(function(d){ yLine.push([0, d, 0]); });
  
var yScaleData = yScale3d([yLine]);
processYScaleData(yScaleData);

function processYScaleData(data){
    var yScale = svg.selectAll('path.yScale').data(data);

    yScale
    .enter()
    .append('path')
    .attr('class', '_3d yScale')
    .merge(yScale)
    .attr('stroke', 'red')
    .attr('stroke-width', .5)
    .attr('d', yScale3d.draw);
  
    yScale.exit().remove();
};

// z axis
var zScale3d = d3._3d()
    .shape('LINE_STRIP')
    .origin(origin)
    .rotateX(alpha)
    .rotateY(beta)
    .scale(scale);

d3.range(-5, 10, 1).forEach(function(d){ zLine.push([0, 0, d]); });
  
var zScaleData = zScale3d([zLine]);
processZScaleData(zScaleData);

function processZScaleData(data){
    var zScale = svg.selectAll('path.zScale').data(data);

    zScale
    .enter()
    .append('path')
    .attr('class', '_3d zScale')
    .merge(zScale)
    .attr('stroke', 'green')
    .attr('stroke-width', .5)
    .attr('d', zScale3d.draw);
  
    zScale.exit().remove();
};
広告
お問い合わせは sweng.tips@gmail.com まで。
inserted by FC2 system