System.out.println("Java学習中");

Java Silver対策 / Suno AI作曲 / 星読み×IT 💻「技術と感性」を学ぶポートフォリオブログ

【ポートフォリオ改善】MP3プレイヤーの実装と、モーダルを閉じたら音が止まるJavaScriptの書き方

🟢 はじめに

現在作成中のポートフォリオサイトには、Suno AIで作成した楽曲を掲載しているのですが、ふとこんなことを思いました。

『YouTubeで聴く』だけでなく、サイト上でサクッと聴ける『MP3』や、プロンプトが見られる『Suno AI』へのリンクも追加した方が親切かも…?

今回は、ポートフォリオを見に来てくれた方へ「最高のおもてなし(UX)」をするために、サイトを改修したお話です。


🍽️ 音楽の提供方法をレストランに例えてみる

どのリンクを置くべきか迷ったので、ポートフォリオを「冒険者が集うレストラン」に例えて考えてみました。

すでに設置されている「YouTubeで聴く」は、映像という豪華な演出付きで作品を味わってもらう「メインディッシュ」だとしたら、他の2つはこんな役割になります。

1️⃣「MP3を聴く」を追加する場合

これは、お客さんにサクッと味見をしてもらう「試食コーナー」のような役割です。

⭕メリット: YouTubeのように別アプリが開いたり、広告が入る煩わしさがなく、純粋に「音」だけをスピーディーに楽しんでもらえます。

❌デメリット: クリックした時に音声ファイルが「ダウンロード」される設定だと、スマホで見ている人には少し面倒に感じられてしまいます。

もし「MP3」にするなら、別のページに飛ばすよりも、HTML<audio>タグを使って「その場で再生できるプレイヤー」を配置するのがベストです。

画面を移動せずにすぐ聴ける親切な設計になります。

2️⃣「Sunoで聴く」を追加する場合

こちらは、シェフがどうやって料理を作ったかを見せる「オープンキッチン(レシピの公開)」のような役割です。

⭕メリット: Suno AIの共有リンクに飛ぶことで、「どんなプロンプト(指示文)で作ったのか」という裏側を見せられます。 AIツールを使いこなすスキルをアピールするのにぴったりです。

❌デメリット: Suno AIを知らない人にとっては「Sunoって何だろう?」と少し戸惑わせてしまう可能性があります。


🤔 どちらを選べばよいか?

ポートフォリオを見る人(採用担当者やクライアント)「何を一番アピールしたいか」で決めるのがおすすめです。

🧙‍♂️ AIを活用するスキル(プロンプト作成能力など)を評価してほしい場合
「Sunoで聴く」が良いですね。実績アピールに直結します。

🎵 曲の雰囲気や世界観を、手軽にたくさんの人に聴いてほしい場合
「MP3を聴く」(サイト内への音声プレイヤー埋め込み)が圧倒的におすすめです!

今回は、見てくれる人への「最高のおもてなし」を第一に考え、サイトを移動せずにその場でサクッと聴ける「MP3プレイヤー(<audio>タグ)」を導入することにしました。


💿 小さな音楽プレイヤーを設置する

HTML<audio>タグは、ウェブページ上にポンと置ける「魔法のプレイヤー」のようなアイテムです。

💻 追加するHTMLコード

YouTubeボタンのすぐ上にプレイヤーを配置するのが自然だと思い、以下のようにコードを追加しました。

<div class="work-modal__text">
  <p>静かで孤独な冷たい世界から、自分の中の光に気づく物語を描いています。</p>
  <p>「自分を受け入れることで世界が変わる」「自分の力で希望をつかめる」というテーマを軸に作曲しました。</p>
  <p>この曲が、同じように自己嫌悪で自分を傷つけてしまう人へ、そっと届きますように。</p>

  <div class="work-modal__audio" style="margin-top: 24px; margin-bottom: 24px;">
    <audio controls src="audio/月夜の刃.mp3" style="width: 100%;">
      お使いのブラウザは音声再生をサポートしていません。
    </audio>
  </div>
  <div class="work-modal__actions">
    <a class="work-modal__btn" href="https://youtu.be/3Fp7aZ3LEHY" target="_blank">
      YouTubeで聴く
    </a>
  </div>
</div>

📝 コードの解説(プレイヤーの仕組み)

<audio>タグの中で使っている指示文(属性)は、こんな役割を持っています。

controls
これを書くだけで、ブラウザが自動的に「再生ボタン▶️」「音量調節🔊」などの操作パネルを召喚してくれます。

src="〜"(ソース)
プレイヤーに「どの曲(MP3)を入れるか」を指示します。

style="width: 100%;"
プレイヤーの横幅を、親要素の枠いっぱいに広げるおまじないです。
これを入れると、スマホでもパソコンでも綺麗なバランスで表示されます。

お使いのブラウザは〜
万が一、古いブラウザでプレイヤーが表示できなかった時だけ現れる「安全装置」のテキストです。

💡 ワンポイント

音楽ファイルaudiomusic といった専用のフォルダを作って入れておくと、ファイルが迷子にならず整理整頓できるのでおすすめです。


⚠️ トラップ発生!モーダルを閉じても音が鳴り止まない問題

プレイヤーを設置して喜んだのもつかの間。

ウェブサイト制作「あるあるトラップ」に引っかかりました💦

作品の詳細画面(モーダル)を閉じても、音楽が鳴り止まない。

例えるなら、「音楽プレイヤーを再生したまま、部屋のドアをバタンと閉めてしまった状態」です。

ドアを閉めてプレイヤーが見えなくなっても、部屋の中ではずっと曲が流れ続けてしまっているわけです。

これを解決するには、JavaScriptにお願いして「ドアを閉めるときは、ついでにプレイヤーの『一時停止ボタン』も押してね!」と指示を出す必要があります。


🟨 JavaScriptに「自動停止」をお願いする

私はモーダルの実装に「Modaal」というjQueryの拡張機能を使っています。

このModaalには、「モーダルが閉じる直前に、自動的に特定の処理を行う(before_close)」という便利な機能が最初から備わっています。

💻 修正するソースコード(works.js

initModal() という関数を、以下のように書き換えます。

function initModal() { 
  if (typeof $ === "undefined" || !$.fn.modaal) return; 
  
  $(".modal-open").modaal({ 
    overlay_close: true, 
    type: "inline", 
    background: "#000", 
    overlay_opacity: 0.6,
    // ▼▼▼ ここから追加:閉じる直前に発動する魔法 ▼▼▼
    before_close: function() {
      // ページ内のすべての <audio> タグを探して一時停止する
      const audios = document.querySelectorAll('audio');
      audios.forEach(audio => audio.pause());
    }
    // ▲▲▲ ここまで追加 ▲▲▲
  }); 
}

📝 コードの解説

before_close: function() { ... }「ドアが閉まる直前に、中の処理を実行してね」という指示です。

querySelectorAll('audio') : ページの中にある「MP3プレイヤー」をすべて探し出します🔍

forEach(audio => audio.pause())見つけ出したすべてのプレイヤーの「一時停止ボタン」をポチポチッと順番に押していきます。


🛡️ YouTubeも止まらない問題

実はポートフォリオのTopページには、YouTubeの動画<iframe>)も埋め込んでいるのですが、こちらもモーダルを閉じても裏で再生され続けてしまうというトラップが潜んでいました💦

せっかくなので、「MP3もYouTubeも、どちらもピタッと止めるコード」にアレンジしてみます。

💻 修正する箇所(Top.js

$(function () {
    $('.modal-open').modaal({
        overlay_close: true,
        type: 'inline',
        background: '#000',
        overlay_opacity: 0.6,
        // ▼▼▼ ここから追加:閉じる直前に発動する魔法 ▼▼▼
        before_close: function() {
            // ① MP3(audioタグ)を探して一時停止する
            const audios = document.querySelectorAll('audio');
            audios.forEach(audio => audio.pause());

            // ② YouTube動画(iframeタグ)を探してリセット(停止)する
            const iframes = document.querySelectorAll('iframe');
            iframes.forEach(iframe => {
                // iframeのソース(URL)を再度読み込ませることで、再生を強制ストップ!
                const iframeSrc = iframe.src;
                iframe.src = iframeSrc; 
            });
        }
        // ▲▲▲ ここまで追加 ▲▲▲
    });
});

🔍 YouTubeを停止するテクニックの解説

YouTubeの動画<iframe>(アイフレーム)という「別の窓」で動いているため、外から一時停止ボタンを押すのが少し難しい構造になっています。

そこで、「窓枠(src)を一度パタンと閉じて、もう一度サッと開き直す(URLを再セットする)」というテクニックを使いました。

こうすることで再生状態がリセットされ、裏で音が鳴り続けるのを防ぐことができます。


✍️ まとめ

お客さんにサクッと味見をしてもらう「試食コーナー」を作ったことで、ポートフォリオサイトを訪れた人が気軽に楽曲を楽しめる、より親切なサイトになったのでは?と思います。

同じように「ポートフォリオにMP3の再生ボタンを追加したいけど、閉じても音が鳴り止まなくて困っている…」と悩んでいる方の参考になれば嬉しいです🙌


📊【ポートフォリオ改善】JavaScript実装・データ計測

ポートフォリオは、一度作って終わりではありません。

このマガジンでは、JavaScriptを使って「MP3プレイヤー」「モーダルUI」といった魅力的な機能を実装するプロセスと、そのアクションを「GA4(Google Analytics 4)」で計測・分析する実装手順をまとめています。

「機能を作る(実装)」だけでなく、「ユーザーの動きを知る(計測)」という2つの視点からポートフォリオをさらにレベルアップさせていく、そんな実務的なアプローチを共有するマガジンです。


【プロフィール・作品置き場】

Javaの学習記録や、ビジュアルノベル風のオリジナルAI楽曲などをポートフォリオで公開しています!

kenichikamoi.com


Youtube(AI楽曲一覧)はこちら

www.youtube.com