model-viewer
簡単に WebAR する Google 製のライブラリの model-viewer を React で使いたかったが、思いの外まとまった資料が少なく苦労した。ので、メモ。
結論
/** @jsxImportSource @emotion/react */
import { FC } from 'react';
import { css } from '@emotion/react';
import '@google/model-viewer';
declare global {
namespace JSX {
interface IntrinsicElements {
'model-viewer': MyElementAttributes;
}
interface MyElementAttributes {
src: string;
poster: string;
alt: string;
ar: boolean;
scale: string;
}
}
}
type Props = {
poster: string;
glb: string;
usdz: string;
alt: string;
scale?: number;
height?: string;
};
export const ModelViewer: FC<Props> = (props) => {
const { poster, glb, usdz, alt, scale = 1, height = '80vh' } = props;
const container = css`
width: 100%;
model-viewer {
width: 100%;
height: ${height};
}
`;
return (
<div css={container}>
<model-viewer
src={glb}
ios-src={usdz}
poster={poster}
alt={alt}
shadow-intensity="1"
camera-controls
ar
scale={`${scale} ${scale} ${scale}`}
></model-viewer>
</div>
);
};
環境
- react: 18.2.0
- @google/model-viewer: 2.1.1
- @emotion/react: 11.10.5
- node: 16.15.1
mode-viewer を埋め込む
<model-viewer></model-viewer>
を埋め込もうとすると、Property 'model-viewer' does not exist on type 'JSX.IntrinsicElements'.
と怒られてしまう。そこで、
declare global {
namespace JSX {
interface IntrinsicElements {
'model-viewer': MyElementAttributes;
}
interface MyElementAttributes {
src: string;
poster: string;
alt: string;
ar: boolean;
scale: string;
}
}
}
こんな風に宣言してあげる必要がある。MyElementAttributes に書いているのは、-
の入っていないパラメータだ。人によって設定は違うと思うので、怒られながら設定すれば良い。
表示がちっちゃい
デフォルトだと Canvas が、ものすごく小さく表示されてしまうので、画面いっぱいに大きくする。
model-viewer {
width: 100%;
height: ${height};
}
CSS の与え方は何でも良いが、<model-viewer>
という要素に、幅と高さを付ける。今回、幅も高さも画面いっぱい使いたかったのだが、スマートフォンで見た時に、下の方がちょっと切れちゃって、AR ボタンが押せなかったので、80vh
になっている。が、表示したいサイズに合わせて設定。
表示がでっかい
読み込む 3D Model のサイズによるんだろうと思いつつ、AR Mode にした時に、表示される大きさがでかすぎて使いづらい。
そこで、model-viewer
に scale
を設定する。
<model-viewer
src={glb}
ios-src={usdz}
poster={poster}
alt={alt}
shadow-intensity="1"
camera-controls
ar
scale={`${scale} ${scale} ${scale}`}
></model-viewer>
ar-scale="fixed"
にしていると scale
は1(100%)固定のようだ。android と iOS で大きさが違うので、なんだか微妙だが、WebAR で使う 3D Model のポリゴン数には制限があって、それ用に作ると思うので、元を良い感じのサイズで作ってくれ。ということで。
ちょうどカメラのフレーム内に収まるように表示する方法はないものか…
Local のテストでスマホのカメラにアクセスする
$ HTTPS=true yarn start
---
Compiled successfully!
You can now view model3d in the browser.
Local: https://localhost:3000
On Your Network: https://192.168.1.8:3000
Note that the development build is not optimized.
To create a production build, use yarn build.
webpack compiled successfully
Files successfully emitted, waiting for typecheck results...
Issues checking in progress...
No issues found.
https でないと、カメラアクセスはできないので、HTTPS=true
で立ち上げ、On Your Network:
に表示されている 192.168... にアクセスする。
おしまい
最近、3D Model を表示して、WebAR したいみたいな案件は、結構多い。
Three.js
は、そのうち勉強する。