2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SVGでクリックすると音の出るピアノを作る

Last updated at Posted at 2020-09-23

作ったもの

image.png

やること

  • 鍵盤のsvgを作る
  • 音源を作る
  • クリックすると音が鳴るようにする

鍵盤のSVGを作る

Inkscapeを使ってSVGを作ります。1つのキーを1つの<path>で描き、その音階と同じidを振ります。idはオブジェクトのプロパティから編集できます。

image.png

ドの音にあたる位置にはC0~7のキーを書きます。どこのドなのか分かりやすくするためです。

出来上がったらプレーンSVGで保存します。

image.png

保存したSVGをテキストエディタで開くとこのようになってます。
image.png

<svg>タグの中身をHTML内にコピー&ペーストします。
<path>にはfillstrokeを指定するためのstyleが付いていますが、styleはcssで指定したいので削除し、代わりにclassをつけます。

index.html
<svg>
    <path d="M 50,25 v 405 h 80 v -180 h -30 v -225 Z" id="c0" class="white" />
    <path  d="M 100,25 v 225 h 50 v -225 Z" id="cs0" class="black" />
    .
    .
    .
    <path d="M 3970,25 v 405 h 80 v -405 Z" id="c7" class="white" />
    <text x="3988" y="400" class="text">C7</text>
</svg>

(実は初めてのInkscapeだったので上手く作れず、線がガタガタになって見た目が悪かったので、テキストエディタでpathを全て書き直して綺麗に整えました)

CSSでスタイルを指定

SVGでは塗りつぶしはfill、線はstrokeで指定します。
hoverは普通のCSSと同じように指定できます。

キーが分かるように書いたtextは、そのままでは鍵盤をクリックする邪魔になるので、pointer-eventsnoneに指定し、クリックやホバーなどのポインターイベントの対象にならないようにします。
更にuser-selectnoneに指定し文字を選択できないようにします。

piano.css
.white {
  fill: #fff;
  stroke: #000;
  stroke-width: 1px;
  stroke-linecap: butt;
  stroke-linejoin: miter;
}

.white:hover {
  fill: #ccc;
}

.black {
  fill: #000;
  stroke: #000;
  stroke-width: 1px;
  stroke-linecap: butt;
  stroke-linejoin: miter;
}

.black:hover {
  fill: #222;
}

.text {
  fill: #444;
  font-size: 30px;
  font-weight: bold;
  pointer-events: none;
  user-select: none;
}

音源を作る

たまたまインストールされていたStudio Oneと、KEYSCAPEの音源を使ってピアノ音源を作りました。
ピアノを1音ずつ鳴らしたものを、mp3で書き出します。ファイル名は鍵盤のidと同じ音階にします。

image.png

クリックで音を鳴らす

JavaScriptで鍵盤をクリックしたら音が鳴るようにします。
JavaScriptで音声を扱うにはAudioクラスを使います。引数には音声ファイルのパスを指定します。

play.js
const path = document.querySelectorAll('path');

for (let i = 0, l = path.length; l > i; i++) {
  const file = path[i].getAttribute('id');
  const src = `./src/audio/${file}.mp3`;
  const audio = new Audio(src);

  path[i].addEventListener('mousedown', () => {
    audio.currentTime = 0;
    audio.play();
  });
}

querySelectAllで全ての<path>を取得します。

そこからgetAttributeで取得したidをファイル名としてパスを指定し、Audioインスタンスを作成します。

.play()で再生できますが、そのままだと連打しても1つの音の再生が終わるまで他の音を再生してくれないので、よりピアノっぽくする為に、巻き戻してから再生するようにします。再生位置を決めるcurrentTimeに、0をセットするだけです。

参考にしたページ

2
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?