📖

日々の記録 2025-02-16

2025/02/16に公開

メニューを選んでシーンを切り替える。みたいなことがしたい。

ひとまずチュートリアルのさわりができた。
この後いろいろ試してみたいことができたときに、既存のソースを壊すのではなく、別ファイルを切り替えるような形で実現したい。

欲しい機能

  • 手軽に階層型メニューを作成できる
  • 画面をシーン単位で管理して切り替えられるようにする

制限事項

  • iPad 上で動作確認したいので、サーバー側では何も処理をしない

手軽に階層型メニューを作成できるようにする

探してみる

threejs "デバッグメニュー" で検索。期待したものは見つからない

https://www.google.com/search?q=threejs+"デバッグメニュー"&sca_esv=964451d1a588e182&sxsrf=AHTn8zouoAIKOyH0gzFp67uxPIYfnoeMgw%3A1739660135884&ei=ZxuxZ5jXNfTx4-EPg_us4Ag&ved=0ahUKEwjYpreD48aLAxX0-DgGHYM9C4wQ4dUDCBA&uact=5&oq=threejs+"デバッグメニュー"&gs_lp=Egxnd3Mtd2l6LXNlcnAiInRocmVlanMgIuODh-ODkOODg-OCsOODoeODi-ODpeODvCIyBRAAGO8FMgUQABjvBTIIEAAYgAQYogQyBRAAGO8FSJsvUPwOWP8rcAJ4AJABAJgB4AGgAfYEqgEFMC4xLjK4AQPIAQD4AQGYAgWgAogFwgIIEAAYsAMY7wXCAgsQABiABBiwAxiiBMICBBAjGCeYAwCIBgGQBgSSBwUyLjEuMqAH9wc&sclient=gws-wiz-ser

threejs "階層型メニュー" で検索。これも見つからない

https://www.google.com/search?q=threejs+"階層型メニュー"&sca_esv=964451d1a588e182&sxsrf=AHTn8zpBhyFU8O4yLsq0E0ejVjbghZTLQQ%3A1739660380698&ei=XByxZ-yqKs3c2roPgfSG4A8&ved=0ahUKEwjsyJX448aLAxVNrlYBHQG6AfwQ4dUDCBA&uact=5&oq=threejs+"階層型メニュー"&gs_lp=Egxnd3Mtd2l6LXNlcnAiH3RocmVlanMgIumajuWxpOWei-ODoeODi-ODpeODvCIyChAAGLADGNYEGEcyChAAGLADGNYEGEcyChAAGLADGNYEGEcyChAAGLADGNYEGEcyChAAGLADGNYEGEcyChAAGLADGNYEGEcyChAAGLADGNYEGEcyChAAGLADGNYEGEcyChAAGLADGNYEGEcyChAAGLADGNYEGEdIngZQAFgAcAF4AZABAJgBAKABAKoBALgBA8gBAJgCAaACCJgDAIgGAZAGCpIHATGgBwA&sclient=gws-wiz-serp

javascript "階層型メニュー" で検索。少しページがヒットしたが、何かちょっと違う気がする

https://www.google.com/search?q=javascript+"階層型メニュー"&sca_esv=964451d1a588e182&sxsrf=AHTn8zpBhyFU8O4yLsq0E0ejVjbghZTLQQ%3A1739660380698&ei=XByxZ-yqKs3c2roPgfSG4A8&ved=0ahUKEwjsyJX448aLAxVNrlYBHQG6AfwQ4dUDCBA&uact=5&oq=javascript+"階層型メニュー"&gs_lp=Egxnd3Mtd2l6LXNlcnAiImphdmFzY3JpcHQgIumajuWxpOWei-ODoeODi-ODpeODvCIyCBAhGKABGMMESJEdUKYIWMEbcAN4AZABAJgB1wGgAcEPqgEGMC4xMi4xuAEDyAEA-AEBmAIGoALuA8ICChAAGLADGNYEGEfCAggQABiABBiiBMICBRAAGO8FwgIIEAAYogQYiQWYAwCIBgGQBgqSBwMzLjOgB64d&sclient=gws-wiz-serp

web "階層型メニュー" で検索。もしかして階層型メニューではなく、プルダウンメニューの方がよいか ? ホバーメニューとかいう単語も出てきた。

https://www.google.com/search?q=web+"階層型メニュー"&sca_esv=964451d1a588e182&sxsrf=AHTn8zpZbF-ddpl3UW_nFGnhPDqk3z0fwg%3A1739660571693&ei=Gx2xZ_n-KdTa2roPx_n3qAc&ved=0ahUKEwi5-J7T5MaLAxVUrVYBHcf8HXUQ4dUDCBA&uact=5&oq=web+"階層型メニュー"&gs_lp=Egxnd3Mtd2l6LXNlcnAiG3dlYiAi6ZqO5bGk5Z6L44Oh44OL44Ol44O8IjIIECEYoAEYwwRI3xBQhAVY-Q5wAngAkAEAmAGoAaAB2AWqAQMwLjW4AQPIAQD4AQGYAgWgAsYDwgILEAAYsAMYogQYiQXCAggQABiwAxjvBcICCxAAGIAEGLADGKIEwgIKECMYsAMYJxiuApgDAIgGAZAGBpIHAzIuM6AHzgw&sclient=gws-wiz-serp

階層メニュー html で検索。ドロップダウンメニューもそれっぽい。多階層メニューとも呼ぶかも。

https://www.google.com/search?q=階層メニュー+html&oq=階層メニュー+html&gs_lcrp=EgRlZGdlKgYIABBFGDkyBggAEEUYOTIHCAEQABjvBTIKCAIQABiiBBiJBTIGCAMQRRg80gEINTg4OWowajSoAgCwAgE&sourceid=chrome&ie=UTF-8

よさげな解説

https://webdesignday.jp/programing/drop-down-menu/

https://allabout.co.jp/gm/gc/23911/

https://qiita.com/a-takano/items/7715e15a0c263fa6a219

動的に javascript を読み込む

メニューを選んだら該当の javascript を読み込んで実行する。みたいにしたいができるのか?

https://www.softel.co.jp/blogs/tech/archives/6794

できるっぽい

Menu クラスを作成する

概要

TypeScript から メニューを構築しやすくするための機能を提供するクラス

機能

  • 初期化
    • id : "menuroot" がないなら body エレメントの下に追加
  • メニュー項目追加
    • メニュー名、メニューをタップした時に読み込むスクリプトファイル名からメニュー項目を追加。メニュー名は "menu1/menu2" のように記載すると階層構造になる。

コーディング

src/utils/menu.ts を新規作成。

typescript のコメントの書き方

C++ と一緒

/* コメント */
// コメント

クラス定義とコントラクタ

コンストラクタの定義は constructor() で行う。

class Menu {
    constructor() {
        
    }
}

外部公開は export

export { Menu }

add メソッドを追加

GitHub Copilot 君がほぼ期待した実装をしてくれる。
ただ、TypeScript の型エラーが出ている

add(name: string, func: Function) : void {
    // : 
    let menuItem = document.getElementById('menu_' + menu[i])
    // :
    /* 下記でエラー
     Type 'Function' is not assignable to type '(this: GlobalEventHandlers, ev: MouseEvent) => any'.
  Type 'Function' provides no match for the signature '(this: GlobalEventHandlers, ev: MouseEvent): any'.ts(2322)
    */
    menuItem.onclick = func
    // :
}

多分 Element の onclick の型と func の型が違うという意味だと思う。
add の func の型を変えればよいのか ?

ひとまず

menuItem.onclick = () => { func() }

でエラーにならなくなった事は確認したけど、多分これは TypeScript のポリシーに反するんだろうな・・・

add の引数を Function型から変更してみる

https://github.com/TakadaYouhei/threejs-sandbox/commit/709cf0b915bb86aebe0f40a6a59793c451f4142a

-    add(name: string, func: Function) : void {
+    add(name: string, func: (this: GlobalEventHandlers, ev: MouseEvent) => any) : void {

-                menuItem.onclick = () => { func() }
+                menuItem.onclick = func

onclick に代入する部分はスッキリしたけど、 add 関数の引数にちょっと違和感。

私のイメージだと Menu::add はメニューを選択した時に呼ばれる関数をただ記載したいだけなので、元に戻そう。

TypeScript のポリシーに反するかも?とか思ったけど、大事なのはどんなインターフェースにしたいかどうかなのかも。

Discussion