- 状態管理
- スクロールエリア
- r3fでネームプレート
- VRMにアニメーション
- 余白
- ant designの上書き
- フォントを変える
- ARHitTest
- ホームに追加したときのアイコン
- GLTFファイルのS3からの読み込み
状態管理
zustandがいいらしい
ChatGPTに言われるがままにしたので使い方が会ってるのかよくわからないが、とりあえず動いた。
store.tsというのを作って、そこでストアを作成する
変数をセットしたいコンポーネントでストアに保存
そして取得
スクロールエリア
画面内の一部をスクロールエリアにしたい。
はてなブログのブログ記事画面のように。
今はスクロールを一番下にしても真ん中の要素がフッター部分の下に行って見えない。
sectionなどで囲って、styleでoverflow: "auto", maxHeight: "500px"とすればよかった。
簡単。
r3fでネームプレート
r3fでアバターのネームプレートを表示する。
3Dのテキストだけだと見ずらいから、影やアウトラインをつけるか、背景にピル型の矩形をつけたい。
ピル型の背景をつけているサンプルがdreiにあった!
https://codesandbox.io/p/sandbox/the-three-graces-0n9it?file=%2Fsrc%2FApp.js%3A6%2C1-6%2C41
htmlを使っている。でもhtmlタグはそのままだと画面に張り付く。でもサンプルだと張り付いてないな・・・
transformって書くだけでbillboardにならなくなった。
geometryでroudedPlaneGeometry使わなくても別にピルにできる。
ちなみにgeometryはmaathという別のライブラリを使っている。使おうとしたが <roundedPlaneGeometry>はエラーが出た。
AR/VRモードに入るとhtmlで書いた要素は表示されなかった・・・
しょうがないのでhtml使わないことにした。Unityと同じ感じで、ネームプレート用の画像を用意して、それをplaneのマテリアルに設定する。
これでできた!透過画像は非同期に読み込まないと透過されなかった。
LookAt
ネームプレートをカメラに向けてlookat
Copilot様の言う通りですんなりできた。空間にカメラ置いてなくても問題なかった
あと複数の要素をまとめるのはgroupというタグを使うとできた。
その際、refはMeshからGroup属性に変えないといけなかった。
VRMにアニメーション
pixivのサンプルだとmixamoのfbxを入れるサンプルはある
ググってもmixamoのファイル入れる記事が多いのはこのせいなのか。
そしてvrmとvrm表示とanimation読み込みとstatus変化が別のコンポーネントにあるせいでどうやって自分のコードで読み込めばいいかわからない;;
シンプルな記事が欲しい
複雑すぎて記事では書けないが、なんだかんだできた。
余白
r3fを表示しているページで、Canvasの周りにちょっとだけ余白があって気になった。
useEffect(() => {
document.body.style.margin = '0';
}, );
これを書いたらなくなった。
ant designの上書き
ant designのDrawerを使ったら、余白が結構大きく設定されてた。もう少し小さくしたい。
<Drawer
bodyStyle={{ padding: 0 }}
としたら上書き設定できた。でも非推奨とは出る。でもビルドしても動いてるしいいやろ。
cssを使った上書きの方法
フォントを変える
昔やった方法でCSSにフォント書いても適用されないと思ってたら、Next.jsのテンプレート特有の問題だった!もーー
layout.tsxにあるimport { Inter } from "next/font/google";を変えたらいい.
よくわからないけどnext.jsがいい感じにフォントを扱ってくれるらしい。
これで一部変わったが、AntDesignのパーツのフォントはほとんど変わらない。
この記事+copilotでなんとかなった。
global.cssなどでフォントを使えるようにしておいて
layout.tsxでConfigProviderを使って設定したらうまくいった!
next/font/googleを使う方法はよくわからなかった
ARHitTest
平面検出してそこにARをだしたい。
reactではない元のWebXRAPIのサンプルでHitTestを動かせる。タップしたところにお花が咲く
webxr-samples/hit-test.html at main · immersive-web/webxr-samples · GitHub
react-xrにもサンプルがあった
このデモで↑のコードと同じような動きをするが、ボックスが平面に沿って動くだけで、よくあるタップしたらそこにモデル表示とか、平面を検出してくださいUIとかは入ってない。
こちらのサンプルが、タップしたところにモデルが表示されて固定される!
デモ
mapに配列としてタップしたときの位置を渡している?
models.map(({ position, id }) => {
return <Model key={id} position={position} />;
})}
タップはレティクル自体をタップする方式だった。
<Interactive onSelect={placeModel}>
<mesh ref={reticleRef} rotation-x={-Math.PI / 2}>
<ringGeometry args={[0.1, 0.25, 32]} />
<meshStandardMaterial color={"white"} />
</mesh>
</Interactive>
あまり一般的ではない気がする。GoogleのネイティブのARは平面検知したらすぐにその場に出た。それがシンプルでいいかも!
あと平面検出してくださいUIは自分で出さないといけないのか・・・
平面検知したかどうかってどうやってとるのだろう?
でうまくいかない
ホームに追加したときのアイコン
Webページをスマホのホーム画面に追加したときのアイコンはファビコンが使われるわけじゃないらしい
<link rel="apple-touch-icon" href="画像パス" />
でもnext.jsで画像読み込みってimageタグ使わないとうまくできない・・・
r3fでマテリアルにテクスチャ読み込むときもうまくできなかった。
imageタグを使わない読み込み方を教えてほしい
ファビコンと同じく、名前を設定してappフォルダの下に置けばいいらしい
これでiOSでは表示されたけど、Androidは表示されない・・・
iconというのも設定した。
絶対パスじゃないといけないとかほかの記事に書いてたけどnext.jsでもそうなのかな
この質問も同じ状況だ。そして解決していない・・・
https://www.reddit.com/r/nextjs/comments/1alwj4w/add_home_screen_icon_on_android_devices/?rdt=34862
GLTFファイルのS3からの読み込み
ローカルのgltfファイル読み込みはVRMファイル読み込みのスクリプトをほんの少し変えたらできた。
loader.register((parser) => {
return new VRMLoaderPlugin(parser)
})
を消すだけ。
VRMファイル読み込みはこちらの記事を参照していた
ローカルの読み込みはできたが、S3に置いたものを読み込めない。copilot的には loader.load(のあとのURLを"model/filename"みたいなローカルのパスから、"https://S3のURL"に置き換えるだけでいいはずなのに・・・
こちらの記事に書いてあるようにgltfを置いてあるS3のパケットの設定でCross-Origin Resource Sharing (CORS)を有効にしたら表示できた。
書く中身はChatGPTに聞いた
[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "GET" ], "AllowedOrigins": [ "*" ], "ExposeHeaders": , "MaxAgeSeconds": 3000 } ]
*1:set) => ({