質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.23%

THREE.jsで作った3DモデルをHTMLのdiv要素内でだけ表示したい(レスポンシブにしたい)

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,918

univmotokazu

score 17

/**文章を見直し、意図が伝わらない文章だったため修正させていただきました*****/
表題の通りなのですが、THREE.jsで作成したアニメーションをページの特定の領域でだけレスポンシブに表示をしたいと考えています。
document.getElementByIdでdiv要素を取得し、そこに描画して後はCSSでサイズや位置をいじればよいだろうと思ったのですが、どうも思ったとおりに行きません。

イメージ説明

このような場合はどのようにコードを書き換えればよいでしょうか?
レスポンシブな表示をすることは難しいのでしょうか.....

よろしくお願いします。

<!-------------------THREE.js------------------------>
    <script>
    if (!Detector.webgl) Detector.addGetWebGLMessage();

    var container, controls;
    var camera, scene, renderer, light, mixer;
    var clock = new THREE.Clock();
    var mesh;

    init();
    animate();

    function init() {
        // container = document.createElement('div');
        container = document.getElementById("threejs");
        // document.body.appendChild(container);

        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 20);
        camera.position.set(-1.8, 0.9, 2.7);

        controls = new THREE.OrbitControls(camera, container);
        controls.target.set(0, -0.2, -0.2);


        scene = new THREE.Scene();

        scene.background = new THREE.Color(0x58a2e2)

        light = new THREE.HemisphereLight(0xffffff, 0x444444);
        light.position.set(0, 200, 0);
        scene.add(light);

        light = new THREE.DirectionalLight(0xffffff);
        light.position.set(0, 200, 100);
        light.castShadow = true;
        light.shadow.camera.top = 180;
        light.shadow.camera.bottom = -100;
        light.shadow.camera.left = -120;
        light.shadow.camera.right = 120;
        scene.add(light);

        // slider
        var params = {
            morphTarget: 0,
        };

        var gui = new dat.GUI();

        var folder = gui.addFolder('Morph Targets');
        folder.add(params, 'morphTarget', 0, 1).step(0.01).onChange(function(value) {
            mesh.morphTargetInfluences[0] = value
        });
        folder.add(params, 'morphTarget', 0, 1).step(0.01).onChange(function(value) {
            mesh.morphTargetInfluences[1] = value
        });

        folder.open();

        // grid
        var grid = new THREE.GridHelper(20, 20, 0x000000, 0x000000);
        grid.material.opacity = 0.2;
        grid.material.transparent = true;
        scene.add(grid);

        // model
        var loader = new THREE.GLTFLoader();
        var filepath = "threejs/models/gltf/test/welcometoblender.gltf";


        loader.load(filepath, function(gltf) {

            gltf.scene.traverse(function(node) {
                if (node.isMesh) mesh = node;
            });

            mesh.material.morphTarget = true;

            scene.add(mesh);




            if (gltf.animations.length > 0) {

                var animationIndexToPlay = 0;



                var animations = gltf.animations;
                if (animations && animations.length) {
                    mixer = new THREE.AnimationMixer(gltf.scene);
                    var animation = animations[animationIndexToPlay];
                    var action = mixer.clipAction(animation);
                    action.play();
                }



            } else {
                alert("Model has NO animations");
            }

            gltf.scene.traverse(function(child) {
                if (child.isMesh) {
                    // handle child objects
                }
            });
        });

        // render
        renderer = new THREE.WebGLRenderer({
            antialias: true
        });
        renderer.setPixelRatio(window.devicePixelRatio);
        /*下の記述でサイズ変更できる?*/
        renderer.setSize(500, 500);
        renderer.gammaOutput = true;
        container.appendChild(renderer.domElement);
        window.addEventListener('resize', onWindowResize, false);
    }

    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }

    function animate() {
        controls.update();
        requestAnimationFrame(animate);
        if (mixer) mixer.update(clock.getDelta());
        renderer.render(scene, camera);

    }

</script>

div要素はbodyタグ中で<div id="threejs"></div> としており、上述したコードはbodyタグの後ろで(</body>から</html>の間)記述しています。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

renderer が、Three.jsの描画部分を担っているということは、既にお分かりだと思います。

ですが、Three.jsで扱っている'renderer'だけでなく、 'camera' にも設定しないと、表示が崩れます。

いわゆるサンプルで「window.innerWidth(同じくinnerHeight)」になっていた部分を、全部指定したいDOMのサイズにしてしまえば解決します。

提示されたソースでいうと、 

function init() {
 camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 20);
 // ↑ここ

//以下略


// init の最期で、コレを呼ぶといいと思います
 onWindowResize();
}

//それとこのあたりも修正
function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
}

camera.aspect は、3D描画されるものの縦横比を設定します。そのため、 window のサイズから違うものを適用したいのであれば、ここのあたりもそろって変えてあげましょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/08 18:53

    ありがとうございます!
    レスポンシブに表示することができました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.23%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る