既存Wordpressサイトに埋め込まれるThree.jsのプログラムを作ってて、以前の納品時に画像ファイル(相対パスで指定してた)が読めなくて失敗したことがあったのでバンドルすることにした。
webpack 画像ファイル バンドル
でググるとどうもurl-loaderというのを使うと良いらしい。
今度はWebpack url-loader
でググると、css(やscss,sass)で使う場合や、HTMLのimg要素で使う場合の情報はたくさんヒットするが、Three.jsのテクスチとして使う場合の情報がなかなか見つからなかったのでまとめておく。
TL;DR
Webpack側
Webpack管理対象に画像ファイルを含める
webpack.config.js
// 他の部分は省略
module: {
rules: [
{
test: /\.(gif|png|jpg)$/,
loader: 'url-loader'
}
]
}
使用側
Image
を介して読み込んだものをTHREE.Texture
に食わせる感じ
// @ts-ignore
import imageData from "このファイルから画像ファイルへの相対パス"
const image = new Image()
const texture = new THREE.Texture(image)
image.onload = () => { texture.needsUpdate = true }
image.src = imageData
ポイント
間違ってたら教えてください。。
- 画像ファイルはurl-loaderによってBase64文字列へエンコードされ、DataURLの形式でバンドル先jsに埋め込まれる。
- tsやjsでimportしている箇所はts-loaderやbabel-loaderによってDataURL(の取得処理)に変換される。
(なので、小さめの画像を複数箇所で使う場合にurl-loaderは有効。) - 画像ファイルのimportについての定義がないせいでimportはエラーを吐く(今回はts-ignoreした)
TypeScript未対応のモジュールをimportするときのエラー対策
TypeScript + Webpack でimport jpg - requireでも取得できるが、文字列は
require(パス).default
で参照する必要がある。 - この場合、url-loaderをfile-loaderに変更すると動かなくなる。
これは、require(パス).default
がファイルのURLであることと、image.src
がURL文字列を受けられないことが原因
つまりimportは、渡されたものがファイルURLなら内容をフェッチし、DataURLならそのまま受け取る機能を持ってるということ???(よくわかってない)
その他参考にした情報
base64-as-texture-threejs.js
webpackでcssとimageをバンドルする
img-loader, file-loader, url-loader, resolve-url-loader の違い
How to use webpack file-loader with three.js?
How to add an image file to Three.js using Base64 encoding