D3.jsでオーディオビジュアライザーみたいなものを作成

今回は、オーディオビジュアライザー(Audio Visualizer)みたいなものを
作ってみようと思います。
D3.js は、4.0 です。

オーディオビジュアライザー

値は乱数ですが、音楽の周波数とかと組み合わせれば、
それらしく表示できるかもしれません。

See the Pen D3_AudioVisualizer by book_stone (@book_stone) on CodePen.

究極を言うと10×10のマスを並べて色を塗っているだけです。
とはいえ、妙に悩んだところもありました。

ソースコード

主だった個所をメモしたいと思います。

// 初期データ
var data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

// 10分割スケール
var dataScale = d3.scaleLinear() 
    .domain([0,100])
    .rangeRound([0,10]);
// 色の取得に使う
var colorScale = d3.scaleLinear() 
    .domain([0,10])
    .range([1, 0.3]);

初期データとスケール設定です。
今回は、data配列に入るデータが、0~100までの値と想定し
それをマス目に対応するよう10分割スケールとしてます。
rangeRound を使うと丸めてくれて整数になるから便利です。

カラースケールは、d3.interpolateWarm(t) を使用するためのもの。
t に 0~1 の値を入れることで色々なカラーが取得できます。
今回は、緑から赤紫の範囲を使用するので、1 ~ 0.3 までにしています。
d3-scale/README.md at master · d3/d3-scale · GitHub

// 升目のもととなる配列を作成
var cells = new Array();
for(var i = 0; i < cols; i++){
  for(var j = 0; j < rows; j++){
    cells.push({ "i": i, "j":j });
  }
}

// 升目オブジェクト
var rects = svg.selectAll(".rects").data(cells).enter()
  .append("rect")
  .attr("x", function(d){ return (width/cols) * d.i;   } )
  .attr("y", function(d){ return (height/rows) * (rows - d.j);  } )
  .attr("width", (width / cols) - 4)
  .attr("height", (height /rows) - 3)
  //.attr("stroke-width",1)
  .attr("rx",2)
  .attr("ry",2)
  .attr("stroke","black");

cells という変数にマス目の位置 (i,j) を持たせて作成しています。
これは、のちに enter() で繰り返し rect オブジェクトを作成したいので
1次元配列にしています。もっといい方法があるかもしれない。

rect オブジェクトの作成は、 位置 (i,j) から x座標とy座標を計算しています。
widthとheightはSVGの幅と高さとマス目分だけ割って、1辺を求めています。
サイズから -4 とか - 3は、少し隙間を出したほうがおしゃれかと思い調整した値です。
attr("rx" 2) と attr("ry",2) は rect を角丸とするため。

// 1秒ごとに更新を呼び出し
d3.interval(update, 150);

// 再描画がするメソッド
function update(){
  // 乱数取得
  var rand = d3.randomUniform(100);  
	// 合計10個の乱数を発生
	for( var data=[], i=10; i--; ) {
		data[ data.length ] = Math.floor( rand() ) ;
	}
  
  rects.attr("fill", function(d){  
    if(dataScale(data[d.i]) >= d.j){ 
      //return "cyan";
      return d3.interpolateWarm(colorScale(d.j));
    }
    else{ return "gray" }; 
  });
}

乱数を取得して、配列に放り込んで、その値によって
rect の色を塗るといったもの。比較的シンプルなつくりではないかと思います。

感想

色々検索してみると、最大のところでいったんバーが浮いたりするなど
こったアニメーションがあるものもありました。
すこし、カクカクしている感もあるので、まだ改良の余地もありそうです。
また、背景や少しマス目の幅や数を変えるだけでも印象が変わるのも面白いです。

ひとまずでした。