【Three.js】Embed a Website in Three.js 3D modeling(3Dモデルにサイトを表示させる)

Three.js

 Three.jsを使って、Webサイトを3Dモデルの画面?に表示させる方法を紹介いたします。動画だったり、自分のWEBサイトだったりを、iframeを使って表示させる方法になります。Demoにあるようなものになります。

【Demo_Phone Model】: https://misora.main.jp/model01/

【Demo_PC Model】: https://misora.main.jp/model02/

応用すれば3DモデルのTVに動画を表示したり、製品の画面の埋め込みに付けるテクニックになります。注意点もございますので、ご参考ください。

1.3Dモデルを作る(Blender)

 画面を埋め込む3Dモデルを作成します。

私は、Blenderを使って3Dモデルを作成しました。

おのおので、3Dモデルを用意する必要がございます。そこまで凝ったものは必要ないと思います。フリーの3Dモデルサイトから調達しても問題ございません。

SmartPhone Model

glTFファイルで、作成したモデルを出力します。(smartphone.glb)

(圧縮で出力すると、Three.jsでDRACOLoaderが必要になります。)

Desktop PC Model

glTFファイルで、作成したモデルを出力します。(desktopPC.glb)

(圧縮で出力すると、Three.jsでDRACOLoaderが必要になります。)

2.3DモデルをThree.jsで表示させる

 Three.jsで3Dモデル表示させましょう。

three.js docs
threejs.org / Loading 3D models

Three.js

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
//import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
const loader = new GLTFLoader();

loader.load( 'models/smartphone.glb', function ( gltf ) {

  gltf.scene.name = "phone";
  gltf.scene.position.set(0, -12, 9.3)// 各自で調整
  gltf.scene.scale.set(48, 48, 48)// 各自で調整

	scene.add( gltf.scene );

}, undefined, function ( error ) {

	console.error( error );

} );
// Light

// 環境光源
const E_light = new THREE.AmbientLight(0xFFFFFF, 0.4);
scene.add(E_light);

// DirectionalLight
const light = new THREE.DirectionalLight( 0xffffff, 4.0 );
light.position.set( -500, 800, 1000 ); //default; light shining from top
light.castShadow = true; // default false
scene.add( light );

//Set up shadow properties for the light
light.shadow.mapSize.width = 512; // default
light.shadow.mapSize.height = 512; // default
light.shadow.camera.near = 1.0; // default
light.shadow.camera.far = 500; // default
function renderLoop() {
    //stats.begin();//stats計測
   
    renderer.render(scene, camera) // render the scene using the camera

    requestAnimationFrame(rendeLoop) //loop the render function
    //stats.end();//stats計測
}

renderLoop() //start rendering

OK!

3.iframeのPlaneを作成(CSS3DRenderer)

 IframeをThree.jsで表示させます。正しくは、canvas内に表示させるものでなく、HTMLのDomを擬似的に3Dに見せているものになります。canvasタグの上面にCSS3DRendererのdivタグが重なります。レイヤーの感覚です。

three.js docs
threejs.org / CSS3DRenderer

HTMLでCSS3DRendererで表示させたいものを記述します。

html (width,heightの値でサイズを調整)

<div id="css3d">
  <iframe id="IFR" class="visible" src="**Your_URL**" width="440" height="900" frameborder="0"></iframe>
</div>

three.js

import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
const scene2 = new THREE.Scene();

// Render
const cssrenderer = new CSS3DRenderer({});
cssrenderer.setSize(window.innerWidth, window.innerHeight);
cssrenderer.domElement.style.position = 'absolute';
cssrenderer.domElement.style.top = 0;
cssrenderer.domElement.style.pointerEvents = 'none'
document.body.appendChild(cssrenderer.domElement);

// Object
const cssobj = document.getElementById("css3d");
let css3dobject = new CSS3DObject(cssobj);
// 3Dモデルと重なるように各自で調整
// Scale
css3dobject.scale.set(0.0135, 0.0135, 0.0135);// 3Dモデルと重なるようにサイズを調整しています。
// Position
css3dobject.position.set( -0.1, 0.63, 0);// 3Dモデルと重なるように各自で調整
// Rotation 
css3dobject.rotation.set(THREE.MathUtils.degToRad(-5),  THREE.MathUtils.degToRad(0), THREE.MathUtils.degToRad(0));// 各自で調整

scene2.add(css3dobject);

 カメラのZが0以下になると非表示するようにしています。3DモデルのCanvas層の上のレイヤーに表示されているので、モデルに隠れることがありません。なので、適宜にCSSで消す必要があります。

function renderLoop() {
    //stats.begin();//stats計測

  // *Hide the back side.
  if(camera.position.z < 0){
      cssobj.style.opacity = 0.0
    }else{
      cssobj.style.opacity = 1.0
    }
  // CSS3DRenderer
    cssrenderer.render(scene2, camera);

    renderer.render(scene, camera) // render the scene using the camera
   
    requestAnimationFrame(rendeLoop) //loop the render function
    //stats.end();//stats計測
}

renderLoop() //start rendering

iframeのPlaneができれば、OK!

*Safari で非表示になる問題(CSS3DRender.jsを修正)

viewElement.style.transformOrigin の箇所を削除する

/*CSS3DRender.js*/

~~

		const domElement = parameters.element !== undefined ? parameters.element : document.createElement( 'div' );

		domElement.style.overflow = 'hidden';

		this.domElement = domElement;

		const viewElement = document.createElement( 'div' );
		//viewElement.style.transformOrigin = '0 0'; // <= *Remove
		viewElement.style.pointerEvents = 'none';
		domElement.appendChild( viewElement );

		const cameraElement = document.createElement( 'div' );

~~

4.3Dモデルとiframeをあわせる

上記のもので、3Dモデルとiframeをあわせれば、完成です!

最後に、画面(iframe)のON,OFFのAnimation設定しましょう。Classを追加・削除する方法で、CSSのkeyframesアニメーションを使い、Fade-Inを実現します。

three.js (Animation Switching)

let CamAnime = true;

document.getElementById("Play-Btn").addEventListener("click", () => function(){ 
  console.log("Play-Btn");

  if(!CamAnime){
    // ON
    document.getElementById('IFR').classList.add("visble"); // AddClass
    document.getElementById("Play-Btn").innerText = "OFF";

    CamAnime = true;
  }else{
    // OFF
    document.getElementById('IFR').classList.remove("visble"); //RemoveClass
    document.getElementById("Play-Btn").innerText = "ON";
    
    CamAnime = false;
  }

}());

CSS (Animation)

#IFR{
    visibility:hidden;
}
#IFR.visble{
    visibility:visible;
    animation-duration: 0.5s;
    animation-name: fade-in;
    animation-timing-function:ease-out;
}
@keyframes fade-in{
    0%{
        visibility:hidden;
        opacity: 0;
    }
    50%{
        visibility:visible;
        opacity: 0.5;
    }
    100%{
        visibility:visible;
        opacity: 1;
    }
}

5.完成!

簡単でしたね!

iframeの平面と3Dモデルをあわせる微調整が地味に大変ですが、CSSのアニメーションとかを凝って制作すればカッコいい感じが作れると思います。ポートフォリオサイトなどで、良く見かけるようになったTipsで、自分でもやってみよと思いチャレンジしました。

仕事などで使えそうな感じなので、備忘録しておきます。

タイトルとURLをコピーしました