Reputation: 370
I load an image to show a sprite.
But it seems that the code proceeds before the image is fully load:
But I don't know how to wait for the image to be fully loaded using Threejs. May I have some help?
The code can be tested here : http://www.planetarium2016.com/sprite.html
Here is my code:
<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 is a little bit old...
Upvotes: 5
Views: 8154
Reputation: 2683
var loader = new THREE.TextureLoader();
loader.load(
'img/url/img.png',
function ( map ) {
// map var is your image
},
function ( xhr ) {
if ( xhr.lengthComputable ) {
console.log( 'percent: ' + (xhr.loaded / xhr.total * 100) );
}
},
function ( err ) {
console.log( 'An error happened' );
}
);
THREE 73
Upvotes: 0
Reputation: 584
I would solve this by using JavaScript promises. I separated your three.js code into two main functions, one for initialization and one for animation with requestAnimationFrame. It's more readable this way especially if you intend to perform an async task:
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 );
}
Upvotes: 7
Reputation: 370
solution here: https://threejs.org/docs/#api/loaders/TextureLoader
this is the code to solve my problem:
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 );
Upvotes: 0