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

Pie*_*mps 5 javascript three.js

我加载图像以显示精灵。

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

但是我不知道如何使用 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>
Run Code Online (Sandbox Code Playgroud)

三 JS TextureLoader有点老了...

nov*_*int 7

我会通过使用 JavaScript 承诺来解决这个问题。我将您的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 );
        }
Run Code Online (Sandbox Code Playgroud)


Pie*_*mps 0

解决方案在这里:https ://thirdjs.org/docs/#api/loaders/TextureLoader

这是解决我的问题的代码:

        var url = "https://codefisher.org/static/images/pastel-svg/256/bullet-star.png";
        var loader = new THREE.TextureLoader();
        var spriteMaterial;
        loader.load(url,
            function(texture)
                {
                    spriteMaterial = new THREE.SpriteMaterial( { map: texture, color: 0x0000ff } );
                }

            );
        var sprite = new THREE.Sprite( spriteMaterial );
Run Code Online (Sandbox Code Playgroud)