リムナンテスは愉快な気分

徒然なるままに、言語、数学、音楽、プログラミング、時々人生についての記事を書きます

【p5.js】絶対和音感アプリの見た目をどうにかする(左半分)

limnanthaceae.hatenablog.com


これの続きです。


どうにかします。
毎回CSSを勉強しては忘れるを繰り返しているのでちゃんと記録しようと思います。
(あと最初にCSS勉強した時のfloatとかtableとかで頑張ってた時代の先入観が抜けない)


この記事での完成形はこんな感じです。

f:id:frecafloros:20210429002941p:plain

右半分に設定(次回作る、と思う)と問題送りや答えの表示などの制御ボタン、左半分にコードと構成音の表示をするという形にします。

領域の整理

htmlを整形します。

<div class="container">
	<div class="obj-left">
		<div class="figure">figure</div>
		<div class="obj-chord">chord: <span id="chordname-txt"></span></div>
	</div>
	<div class="obj-right">
		<div class="config">config</div>
		<div class="c">
			<button class="btn-sound" onclick="buttonSound();">和音再生</button>
		</div>
		<div class="c">
			<button class="btn-answer" onclick="buttonAnswer();">答えの表示</button>
		</div>
		<div class="c">
			<button class="btn-next" onclick="buttonNext();">次の問題</button>
	</div>
</div>


中央寄せ、flexbox
flexbox使いながらmargin: auto;しても中央に行かないので注意

.container{
	display: flex;
	justify-content: center;
}

さて、ビジュアル面を作るためにp5.jsというライブラリを使っていきます。

function setup(){
  createCanvas(300,300).parent('chord-constellation');
  background('skyblue');
}

createCanvas()で描画領域を作成します。これだけでも動きますが、parent()でidを指定すると特定のdiv要素に作ったり複数作ったりすることができます。

下のデモでは分かりやすくするため背景色をbackground('skyblue')(水色)で塗ってあります。


See the Pen
chordtrainer-05
by frecafloros (@frecafloros)
on CodePen.


音の分布

chord constellation(日本語訳がわからない)を描画します。

f:id:frecafloros:20210429003813p:plain

これです。

前節で作ったsetup()にわちゃわちゃ追加していきましょう。
まず、音名を円状に等間隔で並べます。

translate(canvasWidth/2, canvasHeight/2);
const r = 80;
for(let i=0;i<12;i++){
  text(pitch2keyname[i], r*sin(i*TAU/12), -1*r*cos(i*TAU/12));

関数を扱いやすくするために、translate()で座標原点を移動させます。デフォルトは描画領域の左上角が座標原点になりますが、translate(canvasWidth/2, canvasHeight/2)とすると座標原点が描画領域の中央に移動します。

後ろのfor文で0番目のキー=Cから時計回りに音名を並べます。text()を使うと文字を突っ込むことができるのですが、第1引数がテキスト内容、第2引数が横の座標、第3引数が縦の座標だと思います。多分。

円状に並べるので三角関数を使います。sin()とかcos()にはデフォルトでrad(ラジアン)を突っ込むようになっているはずです。p5.jsでTAU=\tau=2\piが使えるので大変便利。


続いて、テキストの細かい設定をします。

textAlign(CENTER,CENTER);
textSize(16);
textFont('Optima');

textAlign()は基準点とテキスト配置の位置関係を表します。textAlign(CENTER,CENTER)なら、基準点はテキストボックスの中央になります。

textSize()で文字の大きさ(px)を指定します。px以外にも指定できるかもしれないけど調べてない。今回は16 pxで作成します。

textFont()で文字のフォントを指定します。デザイン性重視でOptimaを使用。多分webフォントというやつで、特にPCに入ってなくても表示される…と思う。


解答ボタンを押すと和音分布を表す棒が表示されるようにします。

// constellation の棒描画
const l = 50;
let tmpPitch = rootPc;

strokeWeight(2);
stroke(0);
line(0, 0, l*sin(tmpPitch*TAU/12), -1*l*cos(tmpPitch*TAU/12));

strokeWeight(1);
stroke(127);
for(let i=1;i<chord.length;i++){
  tmpPitch = rootPc + chordTypes[chordNum]['chordKeys'][i];
  line(0, 0, l*sin(tmpPitch*TAU/12), -1*l*cos(tmpPitch*TAU/12));
}

line()に直線の起終点の座標を与えると線が引けます。今回は根音だけ線を太く濃くしたいので、そこだけ他とは別に描画しました。


あと流石に300x300はでかすぎたので描画領域を200x200にリサイズ。


See the Pen
chordtrainer-06
by frecafloros (@frecafloros)
on CodePen.


コード名の表示

javascriptでhtmlを操作します。

<div class="obj-left">
	<div id="chord-constellation" class="figure"></div>
	<div class="obj-chord">
		<div id="chordname-txt">
			<span class="chord-name" id="chordname-1"></span><br>
			<span class="chord-element" id="chordname-2"></span>
		</div>
	</div>
</div>


解答ボタンを押したらコードネームを表示するようにします。
javascriptの側で、htmlの要素(ここではspan)にcssのclassを動的に追加します。このclassを予めcssの側で設定しておくことで、cssの適用をon / offで切り替えすることができます。

// chord name表示
targetName = document.getElementById("chordname-txt");
targetName.classList.add("chord-icon");
targetName.classList.add("orange");



See the Pen
chordtrainer-07
by frecafloros (@frecafloros)
on CodePen.


続き。

limnanthaceae.hatenablog.com