[実行サンプル・最新版](click)
*江戸切子、薩摩切子をイメージしKirico Cubeと名付けた。
新型コロナウィルスのため在宅機会が多くなって、ウェブブラウザで3Dオブジェクトを表現するJavaScriptで作られたThree.jsライブラリーを使ってみようと思い立った。
当初は撮りためた写真とbgmを合わせたスライドを作るのが目的だったが、その後3Dオブジェクトをオーデイオに合わせてみようと思い、写真スライド版と音楽を目でも楽しむaudio visualizer バージョンの2本立てとなった。
それまでJavaScriptはウェブブラウザ記事の補助的な意味で使っていた。
久しぶりに最新の作品を整理しておく。
趣味でオブジェクトをウェブブラウザ上で表現すると、オブジェクト数が多いほど見栄えがよいと思い、比較的簡単に大量定義できる手法を物色していた。
出会ったのがこちらのサイト「ICS MEDIAWebGL と JavaScript で学ぶ3D表現Three」Three.jsについて基本編、中級編、応用編と段階を踏み分かりやすく丁寧に説明してある。
GeometryはBufferGeometryUtilsを使って定義し、最終的に一つのmeshにする。 参)BufferGeometryUtils
そのため個々のオブジェクト毎に処理は出来ないので、audioデータを使い、cameraを移動し、spotlightの色に変化を持たせることにした。
<!DOCTYPE html>
<html lang="ja" dir="ltr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="google" content="notranslate" />
<title>Sound Visualizer Kirico version</title>
<link href="https://fonts.googleapis.com/css2?family=Titillium+Web:wght@200&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="css/kl.css" />
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.151.3/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.151.3/examples/jsm/"
}
}
</script>
<script type="module" src ="js/KiricoCube2.js"> </script>
</head>
<body>
<div id="btn_box">
<button id="btnStart">START</button>
<button id="btnStop" hidden>STOP</button>
<span id ="timer"></span>
<span id="music_title"></span>
</div>
<div id="Select_box">
<form name="form1">
<select name="music1">
<!-- music file % img % img width % img height -->
<optgroup label="Top Sound">
<option value="../music/Debbusy-Reverie.mp3%../adimg/eine2.jpg%1200%900">Debbusy - 夢</option>
</optgroup>
<optgroup label="Special Sound">
<option value="../music/Beethoven-Symphony-No9-4th-An-die-Freuode.mp3%../adimg/happy_arcadia.jpg%700%700%sphere">Beethoven - 交響曲第9番 ニ短調 Op.125 「合唱」 第4楽章「歓喜の歌」</option>
<option value="../music/Mascagni-Cavalleria-Rusticana-Intermezzo.mp3%../adimg/l_083.png%500%100%sphere">Mascagni - 歌劇《カヴァレリア・ルスティカーナ》間奏曲</option>
<option value="../music/Albinoni's Adagio in G minor.mp3%../adimg/luai_01.jpg%800%800">Albinoni - アダージョ</option>
<option value="../music2/Songs From A Secret Garden.mp3%../adimg/Secret-Garden2.jpg%1200%800">Songs From A Secret Garden</option>
<option value="../music2/You Raise Me Up.mp3%../adimg/celiticwomen.jpg%600%450%sphere">You Raise Me Up</option>
</optgroup>
<optgroup label="Selected Sound">
<option value="../music/Albeniz-Suite-Espanola-Granada.mp3%../adimg/guitar3.jpg%1240%827">Albeniz - グラナダ</option>
<option value="../music/J.S.Bach-Air-On-G.mp3%../adimg/airgstring.jpg%1348%900">Bach - G線上のアリア </option>
<option value="../music/J.S.Bach-Herz-und-Mund-und-Tat-und-Leben.mp3%../adimg/mariaandbabyjesus_00108484.jpg%1200%1000">Bach - 心と口と行いと生活で </option>
<option value="../music/Beethoven-FurElise.mp3%../adimg/Beethoven_05.jpg%1000%1000">Beethoven - エリーゼのために</option>
<option value="../music/Badarzewska-TheMaidens-Prayer.mp3%../adimg/piano_01.jpg%1600%1360">Bądarzewska - 乙女の祈り</option>
<option value="../music/Beethoven-MoonlightSonata-1.mp3%../adimg/moonlight.jpg%1000%1000">Beethoven - 月光</option>
<option value="../music/Bizet-Carmen-Air-de-Toreador.mp3%../adimg/matador01.jpg%1480%830">Bizet - 歌劇《カルメン》から 第2幕「闘牛士の歌」</option>
<option value="../music/Bizet-LArlesienne-Menuett.mp3%../adimg/flute.jpg%1200%800">Bizet - 組曲《アルルの女》 第2番から 「メヌエット」</option>
<option value="../music/Boccherini-Minuetto.mp3%../adimg/imusici.jpg%1500%1500">Boccherini:弦楽五重奏曲 ホ長調 G.275 第3楽章 「メヌエット」</option>
<option value="../music/Chopin-Etude No.3 In E Major Op .10 No.3.mp3%../adimg/piano_05.jpg%1420%830">Chopin - 別れの曲</option>
<option value="../music/Chopin-Etude-No13-Aeolian-Harp.mp3%../adimg/aeolianharp.jpg%1420%830">Chopin - エチュード 13番「エオリアンハープ」</option>
<option value="../music/Chopin-Etude-No23-WinterWind.mp3%../adimg/piano_05.jpg%1420%830">Chopin - 木枯らし</option>
<option value="../music/Chopin-Fantaisie-Impromptu.mp3%../adimg/piano_05.jpg%1420%830">Chopin - 幻想即興曲</option>
<option value="../music/Chopin-Mazurka-No13.mp3%../adimg/piano_05.jpg%1420%830">Chopin - マズルカ 第13番 イ短調 Op.17-4</option>
<option value="../music/Chopin-MimuteWaltz.mp3%../adimg/dog14.jpg%1440%1100">Chopin - 子犬のワルツ</option>
<option value="../music/Chopin-Nocturne-No1.mp3%../adimg/piano_07.jpg%1420%830">Chopin - Nocturne-No1</option>
<option value="../music/Chopin-Nocturne-No2.mp3%../adimg/piano_07.jpg%1420%830">Chopin - Nocturne-No2</option>
<option value="../music/Chopin-Nocturne-No5.mp3%../adimg/piano_07.jpg%1420%830">Chopin - Nocturne-No5</option>
<option value="../music/Chopin-Nocturne-No8.mp3%../adimg/piano_07.jpg%1420%830">Chopin - Nocturne-No8</option>
<option value="../music/Chopin-Nocturne-No13.mp3%../adimg/piano_07.jpg%1420%830">Chopin - Nocturne-No13</option>
<option value="../music/Chopin-Nocturn-No15.mp3%../adimg/piano_07.jpg%1420%830">Chopin - Nocturne-No15</option>
<option value="../music/Chopin-Nocturne-19.mp3%../adimg/chopin_19_01.jpg%1600%1600">Chopin - Nocturne-No19</option>
<option value="../music/Chopin-Nocturne-20.mp3%../adimg/chopin_ai1.jpg%1600%1600">Chopin - Nocturne-No20</option>
<option value="../music/Chopin-Poronase-No6-Heroic.mp3%../adimg/piano_05.jpg%1420%830">Chopin - ポロネーズ 第6番 変イ長調 「英雄」</option>
<option value="../music/Chopin-WaltzNo1-Op.18.mp3%../adimg/piano_05.jpg%1420%830">Chopin - 華麗なる大円舞曲</option>
<option value="../music/Chopin-Spring-Waltz.mp3%../adimg/piano_05.jpg%1420%830">Chopin - 春のワルツ</option>
<option value="../music/Debussy-Girl-with-Flaxen-Hair.mp3%../adimg/amairo.png%900%700">Debbusy - 亜麻色の髪の乙女</option>
<option value="../music/Debussy-The-sea-1-From-dawn-to-midday-on-the-sea.mp3%../adimg/Debussy.jpg%1024%580">Debbusy - 交響詩《海》 1. 海の夜明けから正午まで </option>
<option value="../music/Debussy-Suite-Bergamasque-Clair-de-Lune.mp3%../adimg/tsukinohikari.jpg%1280%720">Debbusy - 《ベルガマスク組曲》より 3. 月の光 </option>
<option value="../music/Dvorak-Humoresque.mp3%../adimg/train_sunset.jpg%1200%634">Dvorak - ユーモレスク</option>
<option value="../music/Dvorak-Strings-Serenade-1st.mp3%../adimg/Cesky_Castle.jpg%1200%960">Dvorak - 弦楽セレナーデ ホ長調 Op.22 第1楽章</option>
<option value="../music/Elgar-Salut-damour.mp3%../adimg/cello.jpg%1024%672">Elgar - 愛のあいさつ Op.12 (Cello) </option>
<option value="../music/Faure-Sicilienne-Piano.mp3%../adimg/piano.jpg%1024%672">Faure - シシリエンヌ Op.78 [ピアノ版]</option>
<option value="../music/Foster-My-Old-Kentucky-Home.mp3%../adimg/kentuckyhome.jpg%1382%1035">Foster - ケンタッキーの我が家</option>
<option value="../music/Gershwin-Someone-to-Watch-Over-Me.mp3%../adimg/piano_01.jpg%1200%1018">Gershwin - 誰かが私を見つめてる</option>
<option value="../music/Gounod-AveMaria.mp3%../adimg/AveMaria.jpg%600%550%sphere">Gounod - アヴェ・マリア</option>
<option value="../music/Hendel-Lascia-chio-pianga.mp3%../adimg/rinaldo_and_armida_boucher.jpg%1200%950">Hendel - 私を泣かせてください ~涙流れるままに</option>
<option value="../music/Hendel-WaterMusic-No2-AllaHornpipe.mp3%">Hendel - 水上の音楽</option>
<option value="../music/Holst-The-Planets-Mars.mp3%../adimg/2k_mars.jpg%600%600%sphere">Holst:組曲《惑星》から 第1曲「火星」</option>
<option value="../music/Holst-The-Planets-Jupiter.mp3%../adimg/2k_jupiter.jpg%600%600%sphere">Holst:組曲《惑星》から「木星」</option>
<option value="../music/Holst-The-Planets-Jupiter-Thaxted.mp3%../adimg/jupiter_ai2.jpg%1400%1400">Holst:組曲《惑星》から「木星」 [第4主題]</option>
<option value="../music/Ivanovici-Valurile-Dunarii.mp3%../adimg/Dunarii.jpg%1920%1080">Ivanovici -ドナウ川の漣</option>
<option value="../music/J.Strauss2-Die-Fledermaus-Overture.mp3%">Johann Strauss2 - 喜歌劇「こうもり」序曲 </option>
<option value="../music/Johann-Strauss-2-The-Blue-Danube.mp3%../adimg/danube.jpg%1680%769">Johann Strauss2 - 美しく青きドナウ</option>
<option value="../music/Johann-Strauss2-Fruhlingsstimmen.mp3%../adimg/Wilhelm_Gause_Hofball_in_Wien.jpg%600%600%sphere">Johann Strauss2 - 春の声</option>
<option value="../music/Lange-Blumenlied.mp3%../adimg/piano_06.jpg%1480%830">Lange - 花の歌</option>
<option value="../music/Liszt-La-Campanella.mp3%../adimg/lacampanella.jpg%1280%720">Liszt - ラ・カンパネラ</option>
<option value="../music/Liszt-Liebestraum-No3.mp3%../adimg/piano_06.jpg%1480%830">Liszt - 愛の夢</option>
<option value="../music/Liszt-Hungarian-Rhapsodies-No2.mp3%../adimg/piano_05.jpg%1420%830">Liszt - ハンガリー狂詩曲 第2番</option>
<option value="../music/Liszt-Consolation-No3.mp3%../adimg/Consolation.jpg%1536%864">Liszt - コンソレーション 第3番</option>
<option value="../music/Mendelssohn-Auf-Flugeln-des-Gesanges.mp3%../adimg/violinpiano.jpg%1500%1000">Mendelssohn - 歌の翼に</option>
<option value="../music/Mendelssohn-WeddingMarch.mp3%../adimg/lohengrin.jpg%1500%1000">Mendelssohn - 結婚行進曲 </option>
<option value="../music/Miyagi-Haru-no-Umi.mp3%../adimg/koto.jpg%1450%400">宮城道雄 - 春の海</option>
<option value="../music/Monti-Csardas.mp3%../adimg/Csardas.jpg%1024%1024">Monti - チャールダーシュ</option>
<option value="../music/Mozart-EineKleine-1st.mp3%../adimg/eine1.jpg%1350%900">Mozart - アイネ・クライネ・ナハトムジーク</option>
<option value="../music/Pachelbel-Cannon.mp3%../adimg/record.png%1500%800">Pachelbel - カノン</option>
<option value="../music/Ravel-Borelo.mp3%../adimg/flute.jpg%1280%853">Ravel - ボレロ</option>
<option value="../music/Rachmaninov-Prelude-in-Csharp-minor.mp3%../adimg/piano_06.jpg%1480%830">Rachmaninov - 前奏曲 嬰ハ短調 作品3-2 《鐘》</option>
<option value="../music/Rachmaninoff-Paganini-Rhapsody-18th.mp3%../adimg/piano_06.jpg%1480%830">Rachmaninov - パガニーニの主題による狂詩曲 - 第18変奏</option>
<option value="../music/Rodrigo-Concierto de Aranjuez.mp3%../adimg/Aranjuez_02.jpg%800%800">Rodrigo - アランフェス協奏曲 第二楽章</option>
<option value="../music/Romance-SpanishTraditional.mp3%../adimg/guitar.jpg%1530%1142">禁じられた遊び~愛のロマンス</option>
<option value="../music/Saint-Saens-Samson-et-Dalila-Bacchanale.mp3">Saint-saens - サムソンとデリラ</option>
<option value="../music/Sarasate-CarmenFantasy-Habanera.mp3%../adimg/flamenco.jpg%1400%900">Sarasate - カルメン幻想曲</option>
<option value="../music/Sarasate-Zigeunerweisen.mp3%../adimg/violin2.jpg%1600%1066">Sarasate - ツィゴイネルワイゼン</option>
<option value="../music/Satie-Gymnopedies-No1-piano.mp3%../adimg/Adagio.jpg%1000%1000">Satie - ジムノペディ(ピアノ版)</option>
<option value="../music/Satie-Gymnopedies-No1.mp3%../adimg/Adagio.jpg%1000%1000">Satie - ジムノペディ(オーケストラ)</option>
<option value="../music/Schubert-AveMaria.mp3%../adimg/piano_03.jpg%1280%854"">Schubert - アヴェ・マリア</option>
<option value="../music/Schubert-Serenade.mp3%../adimg/piano_07.jpg%1536%864">Schubert - セレナーデ</option>
<option value="../music/Schubert-PianoSonata-No16-1.mp3%../adimg/piano.jpg%1480%830">Schubert - ピアノソナタ 第16番 イ短調 D.845 第1楽章</option>
<option value="../music/Schubert-Wiegenlied.mp3%../adimg/Schubert-Wiegenlied.jpg%1200%640">Schubert - 子守歌</option>
<option value="../music/Schumann-Kinderszenen-Traumerei.mp3%../adimg/kinderszenen.jpg%1440%1440">Schumann - 子供の情景(トロイメライ)</option>
<option value="../music/Schumann-Liszt-Widmung.mp3%../adimg/myrthen.jpg%1200%800">Schumann - ミルテの花</option>
<option value="../music/Sibelius-Finlandia.mp3%../adimg/suntoryhall1.jpg%1600%700">Sibelius - フィンランディア</option>
<option value="../music/Tarrega-Alhambra.mp3%../adimg/alhambra.jpg%1600%1000">Tarrega - アルハンブラの思い出</option>
<option value="../music/Tchikovsky-Melodie.mp3%../adimg/violin3.png%1536%1024">Tchaikovsky - メロディ</option>
<option value="../music/Tchaikovsky-SwanLake-act2-Seane.mp3%../adimg/swanlake5.png%1430%1180">Tchaikovsky - 白鳥の湖 第2幕 情景</option>
<option value="../music/Tchaikovsky-Nutcracker-Pas-de-Deux-Adage.mp3%../adimg/Nutcracker.jpg%1536%864">Tchaikovsky - くるみ割り人形 第2幕第14曲 パドドゥ</option>
<option value="../music/Tchaikovsky-Nutcracker-waltz-flowers.mp3%../adimg/walts_flower.jpg%1400%1100">Tchaikovsky - くるみ割り人形 花のワルツ</option>
<option value="../music/Wagner-Ride of the Valkyries.mp3%../adimg/walkure.jpg%1500%700">Wagner - ワルキューレの騎行</option>
<option value="../music/Wagner-Tannhauser-March.mp3%../adimg/tannhauser.jpg%1500%1000">Wagner-Tannhauser - 大行進曲</option>
<option value="../music/Wagner-Tannhauser-Overture.mp3%../adimg/tannhauser.jpg%1500%1000">Wagner-Tannhauser - 序曲</option>
<option value="../music/Wagner-Die-Meistersinger-von-Nuernberg-Vorspiel-act1.mp3%../adimg/Die Meistersinger von Nürnberg.jpg%1600%1020">Wagner - ニュルンベルクのマイスタージンガー</option>
<option value="../music/Weber-Der-Freischutz-Overture.mp3%../adimg/madannosyasyu.jpg%1376%1032">Weber - 歌劇『魔弾の射手』より「序曲」</option>
<option value="../music/Weber-Aufforderung-zum-Tanz.mp3%../adimg/butoh.jpg%600%600%sphere">Weber - 舞踏への勧誘</option>
</optgroup>
<optgroup label="交響曲・協奏曲など">
<option value="../music/Bach-Brandenburg-Concerto-No3-1st.mp3%../adimg/Brandenburg.jpg%1580%1184">Bach - ブランデンブルク協奏曲 第3番</option>
<option value="../music/Bach-Toccata-and-Fugue.mp3%../adimg/organ2.jpg%1400%1220">Bach -トッカータとフーガ ニ短調 BWV565</option>
<option value="../music/Beethoven-PianoConcerto-No5-1st.mp3%../adimg/piano.jpg%1480%830">Beethoven - ピアノ協奏曲 第5番 「皇帝」 第1楽章</option>
<option value="../music/Beethoven-PianoConcertoNo5-2.mp3%../adimg/piano.jpg%1480%830">Beethoven - ピアノ協奏曲 第5番 「皇帝」 第2楽章</option>
<option value="../music/Beethoven-PianoConcerto-No5-3rd.mp3%../adimg/piano.jpg%1480%830">Beethoven - ピアノ協奏曲 第5番 「皇帝」 第3楽章</option>
<option value="../music/Beethoven-Piano-Sonata-No8-Pathetique-1st.mp3%../adimg/piano.jpg%1480%830">Beethoven - ピアノソナタ 第8番 ハ短調 Op.13 《悲愴》 第1楽章</option>
<option value="../music/Beethoven-PianoSonata-No8-2nd.mp3%../adimg/piano.jpg%1480%830">Beethoven - ピアノソナタ 第8番 ハ短調 Op.13 《悲愴》 第2楽章</option>
<option value="../music/Beethoven-Symphony-No5-1st.mp3%../adimg/Beethoven_01.jpg%1000%1000">Beethoven - 交響曲第5番「運命」第一楽章</option>
<option value="../music/Beethoven-Symphony-No5-2nd.mp3%../adimg/Beethoven_02.jpg%1000%1000">Beethoven - 交響曲第5番「運命」第二楽章</option>
<option value="../music/Beethoven-Symphony-No5-3rd-4th.mp3%../adimg/Beethoven_03.jpg%1000%1000">Beethoven - 交響曲第5番「運命」第三楽章</option>
<option value="../music/Beethoven-Symphony-No5-3rd-4th.mp3%../adimg/Beethoven_04.jpg%1000%1000">Beethoven - 交響曲第5番「運命」第四楽章</option>
<option value="../music/Beethoven-Symphony-No6-1st.mp3%../adimg/karajan.jpg%1440%810">Beethoven - 交響曲第6番「田園」 第1楽章</option>
<option value="../music/Beethoven-Symphony-No6-2nd.mp3%../adimg/karajan.jpg%1440%810">Beethoven - 交響曲第6番「田園」 第2楽章</option>
<option value="../music/Beethoven-Symphony-No6-3rd-4th-5th.mp3%../adimg/karajan.jpg%1440%810">Beethoven - 交響曲第6番「田園」第3,4,5楽章</option>
<option value="../music/Beethoven-Symphony-No9-1st.mp3%../adimg/Beethoven.jpg%1440%810">Beethoven - 交響曲第9番 ニ短調 Op.125 「合唱」 第1楽章</option>
<option value="../music/Beethoven-Symphony-No9-2nd.mp3%../adimg/Beethoven.jpg%1440%810">Beethoven - 交響曲第9番 ニ短調 Op.125 「合唱」 第2楽章</option>
<option value="../music/Beethoven-Symphony-No9-3rd.mp3%../adimg/Beethoven.jpg%1440%810">Beethoven - 交響曲第9番 ニ短調 Op.125 「合唱」 第3楽章</option>
<option value="../music/Beethoven-Symphony-No9-4th.mp3%../adimg/Beethoven.jpg%1440%810">Beethoven - 交響曲第9番 ニ短調 Op.125 「合唱」 第4楽章</option>
<option value="../music/Beethoven-ViolinSonata-No5-Spring-1st.mp3%../adimg/violin3.png%1024%682">Beethoven - ヴァイオリンソナタ 第5番 「春」 第1楽章</option>
<option value="../music/Brahms-Violin-Concerto-3rd.mp3%../adimg/violin3.png%1024%682">Brahms - ブラームス:ヴァイオリン協奏曲 第3楽章</option>
<option value="../music/Brahms-ViolinSonata-No1-1st.mp3%../adimg/violin3.png%1024%682">Brahms - ヴァイオリンソナタ第1番「雨の歌」</option>
<option value="../music/Chopin-PianoConcerto-No1-1st.mp3%../adimg/piano_04.jpg%1200%600">Chopin - ピアノ協奏曲 第1番 ホ短調 Op.11 第1楽章</option>
<option value="../music/Chopin-PianoConcerto-No1-2nd.mp3%../adimg/piano_04.jpg%1200%600">Chopin - ピアノ協奏曲 第1番 ホ短調 Op.11 第2楽章</option>
<option value="../music/Chopin-PianoConcerto-No1-3rd.mp3%../adimg/piano_04.jpg%1200%600">Chopin - ピアノ協奏曲 第1番 ホ短調 Op.11 第3楽章</option>
<option value="../music/Dvorak-Symphony-No9-From-the-New-World.mp3%../adimg/ai_02.jpg%600%600">Dvorak - 交響曲第9番「新世界から」第一楽章 </option>
<option value="../music/Dvorak-Symphony-No.9-2nd.mp3%../adimg/ai_08.jpg%600%600">Dvorak - 交響曲第9番「新世界から」第二楽章 </option>
<option value="../music/Dvorak-Symphony-No9-3rd.mp3%../adimg/ai_06.jpg%600%600">Dvorak - 交響曲第9番「新世界から」第三楽章 </option>
<option value="../music/Dvorak-Symphony-No9-4th.mp3%../adimg/ai_05.jpg%600%6S00">Dvorak - 交響曲第9番「新世界から」第四楽章</option>
<option value="../music/Grieg-PianoConcerto-1st.mp3%../adimg/piano_04.jpg%1400%800">Grieg:ピアノ協奏曲 イ短調 作品16 第1楽章</option>
<option value="../music/Mahler-Symphony-No1-2nd.mp3%../adimg/horn2.jpg%1440%1400">Mahler - 交響曲第1番「巨人」第二楽章</option>
<option value="../music/Mahler-Symphony-No5-4th.mp3%../adimg/mahler.png%1600%898">Mahler - 交響曲第5番 嬰ハ短調 第四楽章 </option>
<option value="../music/Mahler-Symphony-No10-5th.mp3%../adimg/mahler2.png%1000%1000">Mahler - 交響曲 第10番 嬰ヘ長調 第5楽章</option>
<option value="../music/Mahler-Symphony-No10-5th.mp3%../adimg/mahler2.png%1000%1000">Mahler - 交響曲 第10番 嬰ヘ長調 第5楽章</option>
<option value="../music/Mendelssohn-Violin-Concerto-1st.mp3%../adimg/violin_ai1.jpg%1000%1000">Mendelssohn:ヴァイオリン協奏曲 ホ短調 Op.64 第1楽章 </option>
<option value="../music/Mendelssohn-Violin-Concerto-2nd.mp3%../adimg/violin_ai2.jpg%1000%1000">Mendelssohn:ヴァイオリン協奏曲 ホ短調 Op.64 第2楽章</option>
<option value="../music/Mozart-Marriage-of-Figaro-Overture.mp3%../adimg/figaro1.jpg%1350%900">Mozart - 歌劇《フィガロの結婚》序曲 K.492</option>
<option value="../music/Mozart-Symphony-No25-1st.mp3%../adimg/jupiter.jpg%1280%800">Mozart - 交響曲第25番 第一楽章</option>
<option value="../music/Mozart-Magic-Flute-Overture.mp3%../adimg/mateki3.jpg%1340%812">Mozart - 歌劇 《魔笛》 序曲 K.620</option>
<option value="../music/Mozart-Piano-Concerto-No20-1st.mp3%../adimg/Gulda.jpg%1200%1200">Mozart - ピアノ協奏曲 第20番 ニ短調 K.466</option>
<option value="../music/Mozart-PianoConcerto-No21-2nd.mp3%../adimg/Gulda.jpg%1200%1200">Mozart - ピアノ協奏曲 第21番 ハ長調 K.467</option>
<option value="../music/Mozart-PianoConcerto-No23-2nd.mp3%../adimg/Gulda.jpg%1200%1200">Mozart - ピアノ協奏曲 第23番 イ長調 K.488</option>
<option value="../music/Mozart-SymNo41-1.mp3%../adimg/jupiter.jpg%1200%800">Mozart - 交響曲第41番「Jupiter」第一楽章</option>
<option value="../music/Mozart-Symphony-No41-2nd.mp3%../adimg/jupiter.jpg%1200%800">Mozart - 交響曲第41番「Jupiter」第二楽章</option>
<option value="../music/Mozart-Symphony-No41-3rd.mp3%../adimg/jupiter.jpg%1200%800">Mozart - 交響曲第41番「Jupiter」第三楽章</option>
<option value="../music/Mozart-Symphony-No41-4th.mp3%../adimg/jupiter.jpg%1200%800">Mozart - 交響曲第41番「Jupiter」第四楽章</option>
<option value="../music/Rachmaninov-PianoConcerto-No2-1st.mp3%../adimg/piano_08.jpg%1280%820"> Rachmaninov - ピアノ協奏曲 第2番 第一楽章</option>
<option value="../music/Rachmaninov-PfConNo2-2.mp3%../adimg/piano_08.jpg%1280%820"> Rachmaninov - ピアノ協奏曲 第2番 第二楽章</option>
<option value="../music/Rachmaninov-Piano-Concerto-No2-3rd.mp3%../adimg/piano_08.jpg%1280%820">Rachmaninov - ピアノ協奏曲 第2番 第三楽章</option>
<option value="../music/Smetana-The-Moldau.mp3%../adimg/praha.jpg%1560%1040">Smetanar - 交響詩 《モルダウ》(わが祖国より)</option>
<option value="../music/Tchaikovsky-PianoConcerto-No1-1st.mp3%../adimg/suntoryhall1.jpg%1600%700">Tchaikovsky - ピアノ協奏曲 第1番 第一楽章</option>
<option value="../music/Tchaikovsky-PianoConcerto-No1-2nd.mp3%../adimg/suntoryhall1.jpg%1600%700">Tchaikovsky - ピアノ協奏曲 第1番 第二楽章</option>
<option value="../music/Tchikovsky-PianoConcertoNo1-3.mp3%../adimg/suntoryhall1.jpg%1600%700">Tchaikovsky - ピアノ協奏曲 第1番 第三楽章</option>
<option value="../music/Tchaikovsky-Symphony-No4-4th.mp3%../adimg/suntoryhall1.jpg%1600%700">Tchaikovsky - 交響曲 第4番 第4楽章</option>
</optgroup>
</select>
</form>
</div>
<canvas id="myCanvas"></canvas>
</body>
</html>
公開されているJavaScriptライブラリーの配信サイトunpkg.comからダウンロードする指定。versionなどが変わった場合、ここだけの変更で、プログラム内部の指定を変更する必要がなくなる
<script type="module" src ="js/KiricoCube2.js"> </script>JavaScriptでmoduleをimportするにはここのscript type="module"にする。これにしないとjsのパスの指定でエラーになる
Select box で選択された情報(オーディオfile名、画像file名、画像width , 画像height , 球体(sphere)か)、をJavaScriptプログラムに渡す
<canvas id="myCanvas"></canvas>描画するcanvas id を指定
body {
margin: 0;
background-color:#000000;
overflow: hidden;
font-family: "Titillium Web", sans-serif;
}
#text {
margin-top: -50px;
}
#btn_box {
width: 100%;
}
#btn_box button {
border: 1px solid aliceblue;
border-radius: 2px;
color: gold;
margin: 0px auto;
background: transparent;
}
#btnStart,
#btnStop {
padding: 5px;
}
#timer {
width: 15%;
font-size: 0.8rem;
color: white;
text-align: left;
margin-right: 0.8rem;
text-shadow: 0px 0px 10px black;
}
#music_title {
color: gold;
}
@media (max-width: 480px) {
#music_title {
font-size: 0.8rem;
}
}
htmlで指定したgoogleフォントの指定
@media (max-width: 480px) {スマホ対応(responsive)
// ------------------------- Kirico cube v2 with audio 2023/07/12
import * as THREE from "three";
// import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { FontLoader } from "./FontLoader.js";
import { TextGeometry } from "./TextGeometry.js";
import * as BufferGeometryUtils from "three/addons/utils/BufferGeometryUtils.js";
// ----- Start butoon ------------------------------------
btnStart.addEventListener("click", (value) => {
btnStart.hidden = true;
btnStop.hidden = false;
Select_box.hidden = true;
const music1 = document.form1.music1;
const num = music1.selectedIndex;
const str = music1.options[num].value;
var str2 = str.split('%', 5);
var music = str2[0]; // music mp3
var imgf = str2[1]; // img file jpg
var imgw = str2[2]; // img width
var imgh = str2[3]; // img height
var shape = str2[4]; // style sphere or cube
if (imgf === "") { var imgf = "../adimg/record.jpg", imgw = 1200, imgh = 630 }; // defult img set
var mtitle = music.replace(".mp3", "").replace("./music/", "").replace("./music2/", "").replace(".", "").replace("-", " ");
console.log(mtitle)
document.getElementById("timer").textContent = "loading ... ";
document.getElementById("music_title").textContent = " " + mtitle + " ";
var loader = new THREE.TextureLoader();
// winodows size get
const canvasElement = document.querySelector("#myCanvas");
const width = window.innerWidth;
const height = window.innerHeight;
// ------------------------------------------- constant set
const fft_size = 512; // fft size
var audioDuration = 0;
let h2 = 0;
var endflag = 0;
var tmsh = 0; // textMesh defined
let radiuscamera = width<480 ? width*8 : width *4;
var anglecamera = 0; // camera angle
let crotsw = 1; // camera rotation
let m1defsw = 0; // mesh1 defined
var Myreq; // animationframe id
let cyarg = 0.2; // camera y move arg
let czarg = 1; // camera z move arg
// ------------ audio --------------------------------------------------------
const audioElement = new Audio(music);
const context = new AudioContext(); // audio context define
var ctimesave = 0; // timer save
audioElement.play();
audioElement.addEventListener("loadedmetadata", function (e) {
audioDuration = audioElement.duration; // 再生総時間を取得する
});
// -------------------------------------
// audio analize
// -------------------------------------
let nodeAnalyser = null;
const freqByteDataArray = [];
// ----- initalize
for (let i = 0; i < fft_size / 2; i++) {
const array = new Uint8Array(fft_size / 2);
for (let j = 0; j < fft_size / 2; j++) {
array[j] = 0;
}
freqByteDataArray.push(array);
}
initSound();
function initSound() {
const obj = analyseSound(audioElement);
nodeAnalyser = obj.nodeAnalyser;
}
// -- analizer
function analyseSound(audioElement) {
const nodeAnalyser = context.createAnalyser();
nodeAnalyser.fftSize = fft_size;
nodeAnalyser.smoothingTimeConstant = 0.9;
nodeAnalyser.connect(context.destination);
const nodeSource = context.createMediaElementSource(audioElement);
nodeSource.connect(nodeAnalyser);
return { nodeAnalyser };
}
// ----------------- 3d define ------------------------------------------------
// レンダラーを作成
const renderer = new THREE.WebGLRenderer({
canvas: canvasElement, alpha: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
// renderer.setClearColor(0xb0c4de);
// シーンを作成
const scene = new THREE.Scene();
// カメラを作成
let cposx = 0; // camera position initial
let cposy = 0;
let cposz = radiuscamera;
let anglecamera_x = 0 ; // camera move
let anglecamera_y = 0 ;
let anglecamera_z = 0 ;
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 13000);
camera.aspect = width / height;
camera.updateProjectionMatrix();
camera.position.set(cposx, cposy, cposz); // -- position initial
// ------------------ sphere define
if (typeof shape === "undefined") { // shape not defined
document.body.style.backgroundImage = "url(" + imgf + ")"; // --- background image
document.body.style.backgroundRepeat = "no-repeat";
document.body.style.backgroundPosition = "50% 50%"; // x y
document.body.style.backgroundSize = 30 * imgw / width + "%";
};
var ssz = 0.2;
var mposx = 0; // sphere position
var mposy = 0;
var mposz = 0;
var geometry1 = new THREE.SphereGeometry(imgw * ssz, imgh * ssz, 100)
var material1 = new THREE.MeshPhongMaterial({ map: loader.load(imgf), transparent: true, opacity: 1 });
const mesh1 = new THREE.Mesh(geometry1, material1);
if (shape === "sphere") {
scene.add(mesh1);
mesh1.position.set(mposx, mposy, mposz) // image position
m1defsw = 1;
};
// 1辺あたりに配置するオブジェクトの個数
const cell_num = 50;
// 結合用のジオメトリを格納する配列
const boxes = [];
for (let i = 0; i < cell_num; i++) {
for (let j = 0; j < cell_num; j++) {
for (let k = 0; k < cell_num; k++) {
// 立方体個別の要素を作成
const geometrySphere = new THREE.SphereGeometry(2, 2, 2);
// 座標調整
const geow = 50; // 間隔
const geometryTranslated = geometrySphere.translate(
geow * (i - cell_num / 2),
geow * (j - cell_num / 2),
geow * (k - cell_num / 2)
);
// ジオメトリを保存
boxes.push(geometryTranslated);
}
}
}
// box ジオメトリを生成
const geometry = BufferGeometryUtils.mergeGeometries(boxes);
// マテリアルを作成
const material = new THREE.MeshStandardMaterial({ color: 0xffffff, wireframe: true });
// メッシュを作成
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// -------------------------------------------------
// text define
// textMesh : page title
// -------------------------------------------------
const fsize = 30;
var text = mtitle;
if (tmsh == 1) { scene.remove(textMesh) }
const loadert = new FontLoader()
loadert.load('./fonts/optimer_regular.typeface.json', function (font) {
const textGeometry = new TextGeometry(text, {
font: font,
size: fsize,
height: 1,
});
const textMaterial = new THREE.MeshPhongMaterial({ color: 0xffffff });
var textMesh = new THREE.Mesh(textGeometry, textMaterial);
scene.add(textMesh);
textGeometry.center(); // text on center position set
textMesh.position.set(0, 200, 0);
textMesh.rotation.set(- Math.PI / 5, 0, 0);
});
// --------------------- 環境光 を作成 -------------------------------
const ambientLight = new THREE.AmbientLight(0x444444);
scene.add(ambientLight);
// ------------------ spotlight ---------------------------------------
// new THREE.SpotLight(色, 光の強さ, 距離, 照射角, ボケ具合, 減衰率)
var cpz = 500;
const spotLight1 = new THREE.SpotLight(0xffffff, 1.0, 2000, Math.PI / 8, 1, 0);
spotLight1.position.set(0, 0, 1500);
scene.add(spotLight1);
const spotLight2 = new THREE.SpotLight(0xffffff, 1.0, 2000, Math.PI / 2, 1, 0);
spotLight2.position.set(0, 0, 2000);
scene.add(spotLight2);
// const spotLightHelper1 = new THREE.SpotLightHelper( spotLight1);
// scene.add( spotLightHelper1 );
// const spotLightHelper2 = new THREE.SpotLightHelper( spotLight2);
// scene.add( spotLightHelper2 );
// カメラコントローラー
// const controls = new OrbitControls(camera, canvasElement);
// ---------------------------- define ground grid
const gridColor = new THREE.Color(0x84a2d4);
const grid_size = 8000;
const grid1 = new THREE.GridHelper(grid_size, 100, gridColor, gridColor);
grid1.position.y = -height * 2;
scene.add(grid1);
// ------- tick ---------------
tick();
// 毎フレーム時に実行されるループイベントです
function tick() {
const ctime = parseInt(context.currentTime);
const dtime = parseInt(audioDuration); //-- audio duration
if (ctime > ctimesave || typeof ctimesave === "undefined") {
if (ctime <= dtime && typeof audioDuration !== "undefined" && endflag !== 1) {
var str2 = ctime + " / " + dtime;
document.getElementById("timer").textContent = str2;
if (ctime >= dtime) { endflag = 1, endproc() }; // ------- end proc
};
if (dtime > 600 && ctime % 300 === 0) { crotsw = crotsw * -1 }; // change camera rotation
ctimesave = ctime;
};
const freqByteData = new Uint8Array(fft_size / 2);
nodeAnalyser.getByteFrequencyData(freqByteData);
freqByteDataArray.push(freqByteData);
var value0 = freqByteData[0] / 256 // rotation angle , color
var value1 = freqByteData[1] / 256; //
var value2 = freqByteData[2] / 256; //
// カラー生成 hue , saturation , lightness between 0 - 1.0 hue 0 red
spotLight1.color.setHSL(value0, 1, 0.6);
h2 = h2 < 1 ? h2 += 0.001 : 0;
spotLight2.color.setHSL(h2, 1, 0.6)
// camera move
if (radiuscamera >= 1000) { radiuscamera -= 1; let cyarg = 0.5 }; // mesh1 に接近
anglecamera_x += crotsw * value0 / 10;
anglecamera_y += crotsw * value1 / 10;
anglecamera_z += crotsw * value2 / 10;
camera.position.x = radiuscamera * Math.cos(Math.PI / 180 * anglecamera_x);
camera.position.y = radiuscamera * Math.cos(Math.PI / 180 * anglecamera_y) * cyarg;
camera.position.z = radiuscamera * Math.sin(Math.PI / 180 * anglecamera_z) * czarg;
camera.lookAt(new THREE.Vector3(0, 0, 0)); // 中央に向ける
spotLight1.position.x = radiuscamera * Math.cos(Math.PI / 180 * anglecamera_x);
spotLight1.position.y = radiuscamera * Math.cos(Math.PI / 180 * anglecamera_y) * cyarg;
spotLight1.position.z = radiuscamera * Math.sin(Math.PI / 180 * anglecamera_z) * czarg;
spotLight1.lookAt(new THREE.Vector3(0, 0, 0)); // 中央に向ける
anglecamera += crotsw * value0 / 10;
// spotLight1.target.position.setFromMatrixPosition(camera.matrixWorld);
if (m1defsw === 1) {
mesh1.rotation.y += 0.002;
};
// レンダリング
renderer.render(scene, camera);
var Myreq = requestAnimationFrame(tick);
}; // tick end
// ----------- stop button
btnStop.addEventListener("click", (value) => {
audioElement.pause();
btnStart.hidden = false;
btnStop.hidden = true;
Select_box.hidden = false;
cancelAnimationFrame(Myreq);
location.reload()
});
// ----------------- endproc
function endproc() {
document.getElementById("timer").textContent = " end...push Stop ..";
document.getElementById("music_title").textContent = " ";
camera.position.set(cposx, cposy, cposz); // -- position initial
scene.remove(mesh, grid1);
cancelAnimationFrame(Myreq);
Select_box.hidden = false;
// location.reload()
};
// resize
window.addEventListener('resize', onResize);
function onResize() {
const width = window.innerWidth;
const height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
};
}); // init end
// ------------------------- Kirico cube v2 with audio 2023/07/12
import * as THREE from "three";
// import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { FontLoader } from "./FontLoader.js";
import { TextGeometry } from "./TextGeometry.js";
import * as BufferGeometryUtils from "three/addons/utils/BufferGeometryUtils.js";
// ----- Start butoon ------------------------------------
btnStart.addEventListener("click", (value) => {
btnStart.hidden = true;
btnStop.hidden = false;
Select_box.hidden = true;
const music1 = document.form1.music1;
const num = music1.selectedIndex;
const str = music1.options[num].value;
var str2 = str.split('%', 5);
var music = str2[0]; // music mp3
var imgf = str2[1]; // img file jpg
var imgw = str2[2]; // img width
var imgh = str2[3]; // img height
var shape = str2[4]; // style sphere or cube
if (imgf ==="") {var imgf="../adimg/record.jpg" , imgw = 1200 , imgh = 630 }; // defult img set
var mtitle = music.replace(".mp3", "").replace("./music/", "").replace("./music2/", "").replace(".", "").replace("-", " ");
console.log(mtitle)
document.getElementById("timer").textContent = "loading ... ";
document.getElementById("music_title").textContent = " " + mtitle + " ";
var loader = new THREE.TextureLoader();
// canvas size get
const canvasElement = document.querySelector("#myCanvas");
const width = window.innerWidth;
const height = window.innerHeight;
Three.jsライブラリーは@0.128以降のバージョンで大きく変わって必要な機能だけを外部からインポートするようになった
htmlのimportmapで指定したlinkからTHREE(js)をimport、他にOrbitControls(ここではコメントアウト)、FontLoader、TextGeometryはダウンロードしておいたファイルを指定
BufferGeometryUtilsはthree.jsをダウンロードしたaddonsフォルダー以下にある
htmlのStartボタンbutton id="btnStart"でリンクされ、オーディオなどの情報が格納されている配列からそれぞれ取り出す
const canvasElement = document.querySelector("#myCanvas");widthとheightをwindowから取り出す
// ------------ audio --------------------------------------------------------
const audioElement = new Audio(music);
const context = new AudioContext(); // audio context define
var ctimesave = 0; // timer save
audioElement.play();
audioElement.addEventListener("loadedmetadata", function (e) {
audioDuration = audioElement.duration; // 再生総時間を取得する
});
// -------------------------------------
// audio analize
// -------------------------------------
let nodeAnalyser = null;
const freqByteDataArray = [];
// ----- initalize
for (let i = 0; i < fft_size / 2; i++) {
const array = new Uint8Array(fft_size / 2);
for (let j = 0; j < fft_size / 2; j++) {
array[j] = 0;
}
freqByteDataArray.push(array);
}
initSound();
function initSound() {
const obj = analyseSound(audioElement);
nodeAnalyser = obj.nodeAnalyser;
}
// -- analizer
function analyseSound(audioElement) {
const nodeAnalyser = context.createAnalyser();
nodeAnalyser.fftSize = fft_size;
nodeAnalyser.smoothingTimeConstant = 0.9;
nodeAnalyser.connect(context.destination);
const nodeSource = context.createMediaElementSource(audioElement);
nodeSource.connect(nodeAnalyser);
return { nodeAnalyser };
}
Web Audio APIを使って、 FFT(高速フーリエ変換)で分解されたデータをnodeAnalyserに渡す。参).BaseAudioContext: createAnalyser() method
audioElement.play();audioElement.play();でaudio再生、audioElement.durationでaudioの長さを取得する
// ----------------- 3d define ------------------------------------------------
// レンダラーを作成
const renderer = new THREE.WebGLRenderer({
canvas: canvasElement, alpha: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
// renderer.setClearColor(0xb0c4de);
// シーンを作成
const scene = new THREE.Scene();
// カメラを作成
let cposx = 0; // camera position initial
let cposy = 0;
let cposz = radiuscamera;
let anglecamera_x = 0 ; // camera move
let anglecamera_y = 0 ;
let anglecamera_z = 0 ;
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 13000);
camera.aspect = width / height;
camera.updateProjectionMatrix();
camera.position.set(cposx, cposy, cposz); // -- position initial
// ------------------ sphere define
if (typeof shape === "undefined") { // shape not defined
document.body.style.backgroundImage = "url(" + imgf + ")"; // --- background image
document.body.style.backgroundRepeat = "no-repeat";
document.body.style.backgroundPosition = "50% 50%"; // x y
document.body.style.backgroundSize = 30 * imgw / width + "%";
};
var ssz = 0.2;
var mposx = 0; // sphere position
var mposy = 0;
var mposz = 0;
var geometry1 = new THREE.SphereGeometry(imgw * ssz, imgh * ssz, 100)
var material1 = new THREE.MeshPhongMaterial({ map: loader.load(imgf), transparent: true, opacity: 1 });
const mesh1 = new THREE.Mesh(geometry1, material1);
if (shape === "sphere") {
scene.add(mesh1);
mesh1.position.set(mposx, mposy, mposz) // image position
m1defsw = 1;
};
// 1辺あたりに配置するオブジェクトの個数
const cell_num = 50;
// 結合用のジオメトリを格納する配列
const boxes = [];
for (let i = 0; i < cell_num; i++) {
for (let j = 0; j < cell_num; j++) {
for (let k = 0; k < cell_num; k++) {
// 立方体個別の要素を作成
const geometrySphere = new THREE.SphereGeometry(2, 2, 2);
// 座標調整
const geow = 50 ; // 間隔
const geometryTranslated = geometrySphere.translate(
geow * (i - cell_num / 2),
geow * (j - cell_num / 2),
geow * (k - cell_num / 2)
);
// ジオメトリを保存
boxes.push(geometryTranslated);
}
}
}
// box ジオメトリを生成
const geometry = BufferGeometryUtils.mergeGeometries(boxes);
// マテリアルを作成
const material = new THREE.MeshStandardMaterial({ color: 0xffffff, wireframe: true });
// メッシュを作成
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// -------------------------------------------------
// text define
// textMesh : page title
// -------------------------------------------------
const fsize = 20;
var text = mtitle;
if (tmsh == 1) { scene.remove(textMesh) }
const loadert = new FontLoader()
loadert.load('./fonts/optimer_regular.typeface.json', function (font) {
const textGeometry = new TextGeometry(text, {
font: font,
size: fsize,
height: 1,
});
const textMaterial = new THREE.MeshPhongMaterial({ color: 0xffffff });
var textMesh = new THREE.Mesh(textGeometry, textMaterial);
scene.add(textMesh);
textGeometry.center(); // text on center position set
textMesh.position.set(0, 200, 0);
textMesh.rotation.set(- Math.PI / 5, 0, 0);
});
// ------------------ spotlight ---------------------------------------
// new THREE.SpotLight(色, 光の強さ, 距離, 照射角, ボケ具合, 減衰率)
var cpz = 500;
const spotLight1 = new THREE.SpotLight(0xffffff, 1.0 , 2000 , Math.PI/8, 1, 0);
spotLight1.position.set(0, 0, 1500);
scene.add(spotLight1);
const spotLight2 = new THREE.SpotLight(0xffffff, 1.0 , 2000 , Math.PI/2, 1, 0);
spotLight2.position.set(0, 0, 2000);
scene.add(spotLight2);
// const spotLightHelper1 = new THREE.SpotLightHelper( spotLight1);
// scene.add( spotLightHelper1 );
// const spotLightHelper2 = new THREE.SpotLightHelper( spotLight2);
// scene.add( spotLightHelper2 );
// カメラコントローラー
// const controls = new OrbitControls(camera, canvasElement);
// ---------------------------- define ground grid
const gridColor = new THREE.Color(0x84a2d4);
const grid_size = 8000;
const grid1 = new THREE.GridHelper(grid_size, 100, gridColor, gridColor);
grid1.position.y = -height * 2;
scene.add(grid1);
Three.js各要素の定義
htmlで音楽とともにsphereが定義されていない場合は、canvasの背景に画像を描く
// 1辺あたりに配置するオブジェクトの個数セルの数(ここでは50x50x50)だけ三次元の立方体座標にBufferGeometryUtilsで作成した仮のgeometryに格納し、materialでcolorとwireframeを指定し、最後にmeshにまとめる
色々試行錯誤してみたがwireframeにした方がspotLightの通りがよいようだ
cameraをラジアン(角度)で動かすためorbitcontrolは実際は効かないのでコメントアウトにしてある
// ------- tick ---------------
tick();
// 毎フレーム時に実行されるループイベントです
function tick() {
const ctime = parseInt(context.currentTime);
const dtime = parseInt(audioDuration); //-- audio duration
if (ctime > ctimesave || typeof ctimesave === "undefined") {
if (ctime <= dtime && typeof audioDuration !== "undefined" && endflag !== 1) {
var str2 = ctime + " / " + dtime;
document.getElementById("timer").textContent = str2;
if (ctime >= dtime) { endflag = 1, endproc() }; // ------- end proc
};
if (dtime > 600 && ctime % 300 === 0) { crotsw = crotsw * -1 }; // change camera rotation
ctimesave = ctime;
};
const freqByteData = new Uint8Array(fft_size / 2);
nodeAnalyser.getByteFrequencyData(freqByteData);
freqByteDataArray.push(freqByteData);
var value0 = freqByteData[0] / 256 // rotation angle , color
var value1 = freqByteData[1] / 256; //
var value2 = freqByteData[2] / 256; //
// カラー生成 hue , saturation , lightness between 0 - 1.0 hue 0 red
spotLight1.color.setHSL(value0, 1, 0.6);
h2 = h2 < 1 ? h2 += 0.001 : 0;
spotLight2.color.setHSL(h2, 1, 0.6)
// camera move
if (radiuscamera >= 1000) { radiuscamera -= 1; let cyarg = 0.5 }; // mesh1 に接近
anglecamera_x += crotsw * value0 / 10;
anglecamera_y += crotsw * value1 / 10;
anglecamera_z += crotsw * value2 / 10;
camera.position.x = radiuscamera * Math.cos(Math.PI / 180 * anglecamera_x);
camera.position.y = radiuscamera * Math.cos(Math.PI / 180 * anglecamera_y) * cyarg;
camera.position.z = radiuscamera * Math.sin(Math.PI / 180 * anglecamera_z) * czarg;
camera.lookAt(new THREE.Vector3(0, 0, 0)); // 中央に向ける
spotLight1.position.x = radiuscamera * Math.cos(Math.PI / 180 * anglecamera_x);
spotLight1.position.y = radiuscamera * Math.cos(Math.PI / 180 * anglecamera_y) * cyarg;
spotLight1.position.z = radiuscamera * Math.sin(Math.PI / 180 * anglecamera_z) * czarg;
spotLight1.lookAt(new THREE.Vector3(0, 0, 0)); // 中央に向ける
if (m1defsw === 1) {
mesh1.rotation.y += 0.002;
};
// レンダリング
renderer.render(scene, camera);
var Myreq = requestAnimationFrame(tick);
}; // tick end
currentTimeでaudioの経過時間を取得し、長さ(duration)とともにhtml画面に表示する
var Myreq = requestAnimationFrame(tick);requestAnimationFrame(tick);でtick()との間を毎秒60フレームでブラウザが更新される
const freqByteData = new Uint8Array(fft_size / 2);nodeAnalyzerのfreqByteDataにはFFTで分解された周波数データ(0~255)が配列で渡されるので0~1に変換
anglecamera_x += crotsw * value0 / 10;cameraの動きに変化を持たせるために、周波数データの使い方にもバラエティーを持たせる
// カラー生成 hue , saturation , lightness between 0 - 1.0 hue 0 redfreqByteData[0]のデータを使いcolor.setHSL(hue, saturation , lightness )でspotLight1の色を変化させる。fftサイズの1/2個のデータが配列で渡されるが試行錯誤の結果最初(0)をカメラの移動とcolorの変化に使った。
colorの3要素hue(色相),saturation(彩度),lightness(明度)は0~1の範囲で指定。lightnessはほどよい明るさにする
// ----------- stop button
btnStop.addEventListener("click", (value) => {
audioElement.pause();
btnStart.hidden = false;
btnStop.hidden = true;
Select_box.hidden = false;
cancelAnimationFrame(Myreq);
location.reload()
});
// ----------------- endproc
function endproc() {
document.getElementById("timer").textContent = " end...push Stop ..";
document.getElementById("music_title").textContent = " ";
camera.position.set(cposx, cposy, cposz); // -- position initial
scene.remove(mesh,grid1);
cancelAnimationFrame(Myreq);
Select_box.hidden = false;
// location.reload()
};
// resize
window.addEventListener('resize', onResize);
function onResize() {
const width = window.innerWidth;
const height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
};
}); // init end
Stopボタンの処理。select boxを表示、animationを停止するcancelAnimationFrame(Myreq);は何故か効かない
audio終了の処理。audio apiで取得したdurationをcurrnttimeが過ぎた時呼ばれる。box meshとgridを消しcameraを初期位置。cancelAnimationFrame(Myreq);は何故か効かない
resizeはwindow幅が変更されたeventでkickされ、再度width、heightでrendererにセットする
今年になってマスコミなどでもChatGPTなどのAIに関する記事が頻繁に載るようになった。 自分でもウェブでの情報発信に活用している。
MicroSoft社のBingもチャット(会話)AIだがimage createrもこのAIのアプリとして使える。3D作品のパーツとして音楽にに合った画像を使う際に、AIを利用して作成しているものもある。
この画像はimage createrに「ベートーベンの交響曲「運命」のイメージにあう画像を作って」とプロンプトして作られたうちの一枚。同じくベートーベンの「エリーゼのために」の画像として使った。画像の左下に" lb"のロゴを表示してあれば著作権は問わないという。
コーデングでも活用できる。「three.jsでspotlightのカラーを動的に変化させる方法」というプロンプトに対する回答:
// スポットライト光源を作成
const light = new THREE.SpotLight(0xFFFFFF, 4, 30, Math.PI / 4, 10, 0.5);
scene.add(light);
// スポットライトの色を変更
light.color.setHex(0xFF0000);
もうすでに、プログラム言語を知らなくても、指示するだけでAIがプログラムを作ってブラウザで実行し結果を表示してくれるという。