実際に働くギターを作りましょう🎸 JavaScriptで💻🤘


ギターを作りましょう!まあ、ok、物理ギターではなく、次の最高のもの:デジタル1!興奮?ああ!ちょうど良いロックショーのように.might as well jump 正に!

器具の鍛造
私はいくつかのboilerメッキから始めます:インラインSVGによる単純なHTMLファイル.インライン、私は後で多くのjsを取り付ける必要があるので.私は常にGibson Flying V 'sデザイン、私はインスピレーションとして頭と首を取る.私は、いくつかの線形勾配とドロップシャドウのためのフィルタから始めます:
<svg id="guitar" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 2400 800" preserveAspectRatio="xMidYMid meet" width="2400" height="800">
  <defs>
    <linearGradient id="fretboard" x1="42%" y1="0%" x2="0%" y2="90%">
      <stop offset="0%" style="stop-color: rgb(56, 53, 53);" />
      <stop offset="100%" style="stop-color: rgb(56, 49, 43);" />
    </linearGradient>

    <linearGradient id="fredboardBorder" x1="0%" y1="0%" x2="0%" y2="100%">
      <stop offset="0%" style="stop-color: rgb(111, 111, 111);" />
      <stop offset="53%" style="stop-color: rgb(255, 255, 255);" />
      <stop offset="100%" style="stop-color: rgb(160, 160, 160);" />
    </linearGradient>

    <linearGradient id="fret" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color: rgb(122, 117, 113);" />
      <stop offset="100%" style="stop-color: rgb(56, 49, 43);" />
    </linearGradient>

    <filter id="dropshadow" height="400%">
      <feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
      <feOffset dx="4" dy="4" result="offsetblur"/>
      <feComponentTransfer>
        <feFuncA type="linear" slope="1.5"/>
      </feComponentTransfer>
      <feMerge>
        <feMergeNode/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>
  <!-- ... -->
</svg>
私は基本構造のために多角形を使用します、そして、文字列のためのrecgandと多角形、フレットのための経路
<svg ...>
  <!-- ... -->
  <polygon
    points="
      -10,300 1860,300 1950,230 2380,400
      1950,570 1860,500 -10,500
    "
    fill="url(#fretboard)"
    stroke-width="10"
    stroke="url(#fredboardBorder)"
    style="filter:url(#dropshadow)"
    stroke-linejoin="round"
  />

  <path
    d="
      M110 305 110 495 M220 305 220 495 M330 305 330 495 M440 305 440 495
      M550 305 550 495 M660 305 660 495 M770 305 770 495 M880 305 880 495
      M990 305 990 495 M1100 305 1100 495 M1210 305 1210 495 M1320 305 1320 495
      M1430 305 1430 495 M1540 305 1540 495 M1650 305 1650 495 M1760 305 1760 495
      M1858 305 1858 495
    "
    stroke-width="10"
    stroke="rgb(122, 117, 113)"
  />

  <rect class="string" x="0" y="324.3" width="1864" height="5" fill="#ccc" />
  <rect class="string" x="0" y="353.6" width="1864" height="5" fill="#ccc" />
  <rect class="string" x="0" y="382.9" width="1864" height="5" fill="#ccc" />
  <rect class="string" x="0" y="412.2" width="1864" height="5" fill="#ccc" />
  <rect class="string" x="0" y="441.5" width="1864" height="5" fill="#ccc" />
  <rect class="string" x="0" y="470.8" width="1864" height="5" fill="#ccc" />

  <polygon points="1863,324.3 1980,290 1980,295 1863,329.3" fill="#ccc" />
  <polygon points="1863,353.6 2065,330 2065,335 1863,358.6" fill="#ccc" />
  <polygon points="1863,382.9 2150,365 2150,370 1863,387.9" fill="#ccc" />
  <polygon points="1863,412.2 2150,445 2150,450 1863,417.2" fill="#ccc" />
  <polygon points="1863,441.5 2065,475 2065,480 1863,446.5" fill="#ccc" />
  <polygon points="1863,470.8 1980,505 1980,510 1863,475.8" fill="#ccc" />

  <circle cx="1980" cy="510" r="20" fill="url(#fretboard)" stroke-width="15" stroke="url(#fredboardBorder)" />
  <circle cx="2065" cy="480" r="20" fill="url(#fretboard)" stroke-width="15" stroke="url(#fredboardBorder)" />
  <circle cx="2150" cy="445" r="20" fill="url(#fretboard)" stroke-width="15" stroke="url(#fredboardBorder)" />
  <circle cx="2150" cy="365" r="20" fill="url(#fretboard)" stroke-width="15" stroke="url(#fredboardBorder)" />
  <circle cx="2065" cy="330" r="20" fill="url(#fretboard)" stroke-width="15" stroke="url(#fredboardBorder)" />
  <circle cx="1980" cy="290" r="20" fill="url(#fretboard)" stroke-width="15" stroke="url(#fredboardBorder)" />
</svg>
これは次のようになります.

これまでで最も美しいギターでなく、とにかく!さて、いくつかのJSとCSSでプレイ可能にしましょう!

ギター弦のクランプ
ギター/音楽理論に精通しているあなたのそれらのためにE A d g h e . これらは、フレットが押されたときに演奏されるメモです.各フレットはこれらをハーフノートで増加させるので、最初の文字列については以下のようになります.
E2 > F2 > Gb2 > G2 > Ab2 > A2 > Bb2 > H2 > C3 > Db3 > D3 Eb3 > E3 > ...
一旦ラップがあるならば、1と円によるオクターブ増分は、新たに始まります.With a little help of my friends , 私はこのノートの地図を思いついた.
const noteMap = [
  ['Ab3', 'G3 ', 'Gb3', 'F3 ', 'E3 ', 'Eb3', 'D3 ', 'Db3', 'C3 ', 'B2 ', 'Bb2', 'A2 ', 'Ab2', 'G2 ', 'Gb2', 'F2 ', 'E2 '],
  ['Db4', 'C4 ', 'B3 ', 'Bb3', 'A3 ', 'Ab3', 'G3 ', 'Gb3', 'F3 ', 'E3 ', 'Eb3', 'D3 ', 'Db3', 'C3 ', 'B2 ', 'Bb2', 'A2 '],
  ['Gb4', 'F4 ', 'E4 ', 'Eb4', 'D4 ', 'Db4', 'C4 ', 'B3 ', 'Bb3', 'A3 ', 'Ab3', 'G3 ', 'Gb3', 'F3 ', 'E3 ', 'Eb3', 'D3 '],
  ['B4 ', 'Bb4', 'A4 ', 'Ab4', 'G4 ', 'Gb4', 'F4 ', 'E4 ', 'Eb4', 'D4 ', 'Db4', 'C4 ', 'B3 ', 'Bb3', 'A3 ', 'Ab3', 'G3 '],
  ['Eb5', 'D5 ', 'Db5', 'C5 ', 'B4 ', 'Bb4', 'A4 ', 'Ab4', 'G4 ', 'Gb3', 'F4 ', 'E4 ', 'Eb4', 'D4 ', 'Db4', 'C4 ', 'B3 '],
  ['Ab5', 'G5 ', 'Gb5', 'F5 ', 'E5 ', 'Eb5', 'D5 ', 'Db5', 'C5 ', 'B4 ', 'Bb4', 'A4 ', 'Ab4', 'G4 ', 'Gb4', 'F4 ', 'E4 ']
]
(最低ノートが頭の近くにあるので、ここを左に曲がっていることに注意してください)
今、私は文字列をクリックできるようにする必要があります.理想的には、私は文字列を再生するための注意を把握するために選択された場所を把握するためにすべての文字列のすべてのフレットにClickable領域を追加します.私は、それをダイナミックにSVGに加えることによって、JSとそれをします.私もグローバルフラグを追加isPlaying マウスが押されたかどうかを判断する.The playNote() 関数は現在再生される注記を出力します.
let isPlaying = false

function playNote (stringKey, note, force = false) {
  if (isPlaying || force) {
    console.log(note)
  }
}

window.addEventListener('mousedown', () => {
  isPlaying = true
})

window.addEventListener('mouseup', () => {
  isPlaying = false
})

const svg = document.querySelector('#guitar')

noteMap.forEach((string, stringKey) => {
  string.forEach((note, noteKey) => {
    const area = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
    area.setAttribute('x', noteKey * 110)
    area.setAttribute('y', 315 + (29.3 * stringKey))
    area.setAttribute('width', 110)
    area.setAttribute('height', 20)
    area.setAttribute('fill', '#fff')
    area.setAttribute('opacity', '0')
    area.addEventListener('click', () => {
      playNote(stringKey, note, true)
    })
    area.addEventListener('mouseover', () => {
      playNote(stringKey, note, false)
    })

    svg.appendChild(area)
  })
})
アクションで見ましょう

次に、3文字の文字列にアニメーションを追加し、文字列を選択したときにユーザーに視覚的なフィードバックを与えます.
const stringVibrationTimes = [0, 0, 0, 0, 0, 0]
const strings = Array.from(document.querySelectorAll('.string'))

setInterval(() => {
  strings.forEach((stringEl, key) => {
    if (stringVibrationTimes[key] > 0) {
      stringEl.classList.add('vibrating')
    } else {
      stringEl.classList.remove('vibrating')
    }

    stringVibrationTimes[key] -= 50

    if (stringVibrationTimes[key] < 0) {
      stringVibrationTimes[key] = 0
    }
  })
}, 50)

function playNote (stringKey, note, force = false) {
  if (isPlaying || force) {
    console.log(note)

    stringVibrationTimes[stringKey] = 3000
  }
}
いくつかのCSS
@keyframes vibrate {
    0% {
        transform: translateY(-2px);
    }
    50% {
        transform: translateY(2px);
    }
    100% {
        transform: translateY(-2px);
    }
}
.string {
    transform: translateY(0);
}
.string.vibrating {
    animation: vibrate .05s infinite;
}
驚くべき

今、音が見つからない!

アンプをクランクアップ!
サウンドを再生するには、MIDIサウンドフォントを使用します.使いましょうmidi-js-soundfonts 閉じるこの動画はお気に入りから削除されています.楽器を使っていますelectric_guitar_clean of FluidR3_GM . 私はサウンドフォントをダウンロードし、フォルダに入れsound/ ブラウザで利用できるようにします.サウンドを再生するにはAudio :
const soundFontUrl = './sound/'
function playNote (stringKey, note, force = false) {
  if (isPlaying || force) {
    console.log(note)
    const audio = new Audio(soundFontUrl + note.trim() + '.mp3')
    audio.play()

    stringVibrationTimes[stringKey] = 3000
  }
}
そして、ここでは完全に作業デモ-文字列を個別にクリックしたり、マウスを押して文字列を横切ってスワイプして再生します.

編集:グラブピック!
コメントでは、カーソルとしてピックを追加することを提案-ちょうど私は、このアイデアをありがとう!
そこで、まずギターピックのSVGを作りました.私は良い形をオンラインで探して、パスと若干のベジエ曲線でそれを再描画しました:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1280 1280" preserveAspectRatio="xMidYMid meet" width="80" height="80">
  <defs>
    <linearGradient id="pickbg" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" style="stop-color:rgb(77, 22, 22);" />
      <stop offset="100%" style="stop-color:rgb(150, 47, 47);" />
    </linearGradient>
  </defs>
  <g transform="rotate(135, 640, 640)">
    <path
      d="M120 310 C 330 -10 950 -10 1160 310 Q 980 1100 640 1210 Q 300 1100 120 310 Z"
      fill="url(#pickbg)"
    />
  </g>
</svg>
SVGを小さくすることが重要であるwidth and height すべてのより大きいSVGがブラウザによって無視されるので、属性.次に、新しいカーソルイメージを本体に適用するだけです.
body {
  /* ... */
  cursor: url(./pick.svg), auto;
}
と実行します:

ニース、すべての岩に準備ができて!

テイクアウト思考
それは、自作より楽しいものでした!このことをすることは本当に難しいです、そして、私はSVGがここでそこで最適化されることができたと確信します、しかし、それは動きます.あなたがこのポストを楽しむならば、あなたの友人に話してください!
私はあなたがこの記事を読んで楽しんだことを願って私はそれを書いて楽しんだ!もしそうならば❤️ または🦄! 私はフリータイムでハイテク記事を書き、毎回コーヒーを飲みたいです.
あなたが私の努力を支持したいならば.buy me a coffee または!