日々の記録 2025-02-16
メニューを選んでシーンを切り替える。みたいなことがしたい。
ひとまずチュートリアルのさわりができた。
この後いろいろ試してみたいことができたときに、既存のソースを壊すのではなく、別ファイルを切り替えるような形で実現したい。
欲しい機能
- 手軽に階層型メニューを作成できる
- 画面をシーン単位で管理して切り替えられるようにする
制限事項
- iPad 上で動作確認したいので、サーバー側では何も処理をしない
手軽に階層型メニューを作成できるようにする
探してみる
threejs "デバッグメニュー" で検索。期待したものは見つからない
threejs "階層型メニュー" で検索。これも見つからない
javascript "階層型メニュー" で検索。少しページがヒットしたが、何かちょっと違う気がする
web "階層型メニュー" で検索。もしかして階層型メニューではなく、プルダウンメニューの方がよいか ? ホバーメニューとかいう単語も出てきた。
階層メニュー html で検索。ドロップダウンメニューもそれっぽい。多階層メニューとも呼ぶかも。
よさげな解説
動的に javascript を読み込む
メニューを選んだら該当の javascript を読み込んで実行する。みたいにしたいができるのか?
できるっぽい
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型から変更してみる
- 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