javascript - Three.js - 如何等待图像加载?

标签 javascript three.js

我加载图像以显示 Sprite 。

但似乎代码在图像完全加载之前继续:

但我不知道如何使用 Threejs 等待图像完全加载。 我可以帮忙吗?

代码可以在这里测试:http://www.planetarium2016.com/sprite.html

这是我的代码:

<html>
    <head>
        <title>My first three.js app</title>
        <style>
            body { margin: 0; }
            canvas { width: 100%; height: 100% }
        </style>
    </head>
    <body>
        <script src="https://rawgithub.com/mrdoob/three.js/master/build/three.js"></script>
        <script>
            var scene = new THREE.Scene();
            var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500);
            camera.position.set(0, 10, 100);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );

            var material = new THREE.LineBasicMaterial({ color: 0x0000ff });
            var geometry = new THREE.Geometry();
            geometry.vertices.push(new THREE.Vector3(-10, 0, 0));
            geometry.vertices.push(new THREE.Vector3(0, 10, 0));
            geometry.vertices.push(new THREE.Vector3(10, 0, 0));
            geometry.vertices.push(new THREE.Vector3(0, 0, -10));

            var line = new THREE.Line(geometry, material);

            scene.add(line);

            var loader = new THREE.TextureLoader();
            var spriteMap = loader.load("https://codefisher.org/static/images/pastel-svg/256/bullet-star.png");

            //+-----------------------------------------------------------+
            //|   I need here to wait for the image to be fully loaded    |
            //|   This cheat is fool: while (spriteMap.image.width == 0); |
            //+-----------------------------------------------------------+

            var spriteMaterial = new THREE.SpriteMaterial( { map: spriteMap, color: 0xffffff } );
            var sprite = new THREE.Sprite( spriteMaterial );
            sprite.scale.set(256, 256, 1);
            sprite.position.set( 0, 0, 10 );
            scene.add( sprite );

            //camera.position.z = 2;

            var render = function () {
                requestAnimationFrame( render );
                renderer.render(scene, camera);
            };
            render();
        </script>
    </body>
</html>

THREE JS TextureLoader有点老了……

最佳答案

我会使用 JavaScript promises 来解决这个问题。我将您的 three.js 代码分成两个主要函数,一个用于初始化,一个用于使用 requestAnimationFrame 进行动画处理。这种方式更具可读性,尤其是当您打算执行异步任务时:

        var scene;
        var camera;
        var renderer;

        var spriteMap;

        var loaderPromise = new Promise(function(resolve, reject) {
            function loadDone(x) {
                console.log("loader successfully completed loading task");
                resolve(x); // it went ok!
            }
            var loader = new THREE.TextureLoader();
            loader.load("https://codefisher.org/static/images/pastel-svg/256/bullet-star.png", loadDone);
        });

        loaderPromise.
            then(function(response) {
                spriteMap = response; //assign loaded image data to a variable
                init(); //initialize the render
                requestAnimationFrame( render );
            }, function(err) {
                console.log(err);
            });

        function init() {
            scene = new THREE.Scene();
            camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500);

            camera.position.set(0, 10, 100);
            camera.lookAt(new THREE.Vector3(0, 0, 0));

            renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );

            var material = new THREE.LineBasicMaterial({ color: 0x0000ff });
            var geometry = new THREE.Geometry();
            geometry.vertices.push(new THREE.Vector3(-10, 0, 0));
            geometry.vertices.push(new THREE.Vector3(0, 10, 0));
            geometry.vertices.push(new THREE.Vector3(10, 0, 0));
            geometry.vertices.push(new THREE.Vector3(0, 0, -10));

            var line = new THREE.Line(geometry, material);
            scene.add(line);

            var spriteMaterial = new THREE.SpriteMaterial( { map: spriteMap, color: 0xffffff } );
            var sprite = new THREE.Sprite( spriteMaterial );
            sprite.scale.set(256, 256, 1);
            sprite.position.set( 0, 0, 10 );
            scene.add( sprite );
        }

        function render() {
            renderer.render(scene, camera);
            requestAnimationFrame( render );
        }

关于javascript - Three.js - 如何等待图像加载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43733088/

相关文章:

javascript - CSS 背景大小规则被覆盖但不确定原因

javascript - Cocoon.js & Three.js : Improving performance

javascript - Three.js - 完美贴合视口(viewport)的广告牌

javascript - 流量: Cannot assign _ to _ because property _ is missing in _

javascript - Three.js - 未捕获的类型错误 : Cannot read property 'normal' of undefined

three.js - 未捕获的类型错误 : Object #<WebGLRenderingContext> has no method 'getShaderPrecisionFormat'

javascript - 三.js错误: "Feedback loop formed between Framebuffer and active Texture" - Rendering Reflections

javascript - AngularJS 路由问题(ui-router)

javascript - 基于offset()创建onClick jquery工具提示。当用户到达底部时,一切都运行良好,工具提示实际上会隐藏

javascript - 函数在循环后返回对象中的未定义值