ThreeJS texture load: black for a while on Firefox - javascript

I want to build an undo/redo feature on a 3D paint tool.
I store the texture in an array after each draw like this:
var image3 = mesh.material.map.image;
var testCanvas = image3.getContext('2d').canvas;
var canvasData = testCanvas.toDataURL("image/jpeg");
undoArray[undoArrayCursor] = canvasData;
To restore it, I am using this code:
var canvasimg = mesh.material.map.image;
var img = new Image();
img.src = srcimg;
var tmpcanvas = document.createElement('canvas');
tmpcanvas.width = canvasimg.width;
tmpcanvas.height = canvasimg.height;
var tmpctx = tmpcanvas.getContext('2d');
tmpctx.drawImage(img,0,0);
var pMap = new THREE.Texture( tmpcanvas );
pMap.flipY = true;
pMap.needsUpdate = true;
pMaterial = new THREE.MeshLambertMaterial( { map:pMap } );
mesh.material = pMaterial;
This is working fine on Chrome and IE but not on Firefox. I get no error/warning message in the console. With Firefox, there is some king of latency. Undo/redo clicks randomly display full black or correct textures. After a while (15-20s), all textures are displayed correctly while I cycle through undo/redo. It looks like it takes a while for Firefox to load the textures. Is there something I missed?

You are not allowing the image to load.
var img = new Image();
img.onload = function(){
var tmpcanvas = document.createElement('canvas');
tmpcanvas.width = canvasimg.width;
tmpcanvas.height = canvasimg.height;
var tmpctx = tmpcanvas.getContext('2d');
tmpctx.drawImage(this,0,0); // notice the "this" instead of img
var pMap = new THREE.Texture( tmpcanvas );
pMap.flipY = true;
pMap.needsUpdate = true;
pMaterial = new THREE.MeshLambertMaterial( { map:pMap } );
mesh.material = pMaterial;
};
img.src = srcimg;
You may have to adjust for variable scope.

Related

Moving image on canvas on the X axis only

The Problem
I am finding it rather difficult to get my head around this, I am attempting to move an image using the mouse along the X axis only. I am finding it hard to even move the image at all and the many tutorials I have looked at arnt really helping me. Here is what I am trying to say:
As you can see by my beautiful image above I only want to image to move left and right at the bottom of the page.
The Code and the Question
Here is my first attempt, when I try this all the images loaded on the canvas no longer appear making it very hard for me to understand why it isnt working.
<script type="text/javascript">
//Referencing the canvas
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var width = canvas.getAttribute('width');
var height = canvas.getAttribute('height');
//Images
var bggameImage = new Image();
var playerImage = new Image();
var enemyImage = new Image();
var projectileImage = new Image();
var livesImage = new Image();
//Canvas dimensions
var width = 480;
var height = 320;
//Loading in the backgroundImage
bggameImage.src = "Images/bggameImage.png";
bggameImage.onload = function(){
context.drawImage(bggameImage, 0, 0);
}
//Loading in the playerImage
playerImage.src = "Images/playerImage.png";
playerImage.onload = function(){
context.drawImage(playerImage, 165, 240);
}
//Loading in the projectileImage
projectileImage.src = "Images/projectileImage.png";
projectileImage.onload = function(){
context.drawImage(projectileImage, 65, 240);
}
var playerImage = {
x:176,
y:74,
}
function init() {
playerImage.src = "Images/playerImage.png";
//Moving player
myCanvas.addEventListener("mousemove", function (e) {
var bounding_box = myCanvas.getBoundingClientRect();
playerImage = (e.clientX - bounding_box.left) * (myCanvas.width / bounding_box.width) - playerImage.width / 2;
playerImage = (e.clientY - bounding_box.top) * (myCanvas.height / bounding_box.height) - playerImage.height / 2;
}
)
</script>
The whole "function init()" part is what I have just tried but I thought I would include this anyway, I understand that I am loading in the playerImage twice.
You're using the same variable name twice (playerImage), so your image is being overwritten. You're using it for the image and also to store the position. Change the playerImage that's storing x and y to be playerPosition or something like that. Update that variable on your mouse event and then render the image according to that variable's values.
Ultimately, you're going to have to look at a game loop using setTimeout or requestAnimationFrame. So, this will become crucial at that stage. And yes, you shouldn't be loading the player image twice either. Do all of that at the start and only start your game when all your assets have successfully loaded.
For instance...
var playerImage;
var alienImage;
var bulletImage;
var assetCount = 0;
function loadAssets() {
playerImage = new Image();
playerImage.onload = checkAssetsLoaded;
playerImage.src = "assets/images/Brush01.png";
alienImage = new Image();
alienImage.onload = checkAssetsLoaded;
alienImage.src = "assets/images/Brush02.png";
bulletImage = new Image();
bulletImage.onload = checkAssetsLoaded;
bulletImage.src = "assets/images/Brush03.png";
}
function checkAssetsLoaded(event) {
assetCount++;
console.log("An asset has loaded!: " + assetCount);
if (assetCount == 3) {
startGame();
}
}
function startGame() {
// Start your game initialization logic here.
console.log("Game starting!");
}

Fabric.js add images order

I'm trying to add images to canvas strictly, but images are added randomly.
What's the problem?
Here is my simple code.
var canvas = new fabric.Canvas("preview");
var imgs = ['bgBottom','bgTop', 'bgLevel', 'bgCircle'];
for (var i=0; i<imgs.length;i++){
var url = imgs[i]+'.png';
fabric.Image.fromURL(url, function (oImg) {
canvas.add(oImg)
})
}
fabric.Image.fromURL loads the image in the background and runs the anonymous function you pass to it once image load is complete which adds it to the canvas. The order that the browser loads the images will vary and you can't rely on it being in a specific order.
Check out this jsfiddle that shows loading an array of images and making sure they're displayed in a set order. This works by adding the image to the canvas before it's loaded; it just doesn't render until the image is available to be displayed.
The code from the jsfiddle:
var SelfLoadingImage = fabric.util.createClass(fabric.Object, {
initialize: function(src) {
this.image = new Image();
this.image.src = src;
this.image.onload = (function() {
this.width = this.image.width;
this.height = this.image.height;
this.loaded = true;
this.setCoords();
this.fire('image:loaded');
canvas.renderAll();
}).bind(this);
},
_render: function(ctx)
{
if (this.loaded) {
ctx.drawImage(this.image, -this.width / 2, -this.height / 2);
}
}
});
var canvas = new fabric.Canvas("preview");
var imgs = [
'http://icons.iconarchive.com/icons/fasticon/ifunny/128/dog-icon.png', // dog
'http://33.media.tumblr.com/avatar_14ee6ada72a4_128.png', // cat
'http://upload.wikimedia.org/wikipedia/commons/b/bc/Nuvola_devices_mouse.png' // mouse
];
for (var i=0; i<imgs.length;i++){
var url = imgs[i];
var img = new SelfLoadingImage(url);
canvas.add(img);
}

Javascript: Correct way to load image to canvas for getImageData?

I wrote a simple libraryless rotozoomer for html5-canvas, and I'm wondering what is the correct way to let image load to canvas before using getImageData?
var hc = document.getElementById("hiddenCanvas"); var hctx = hc.getContext("2d"); // Hidden canvas for imageload (hctx)
var imageObj = new Image(); imageObj.onload = function() { hctx.drawImage(this, 0, 0); }; imageObj.src = 'img/8.jpg';
alert("Click to start");
// This alert needs to be replaced with "hold-the-script-until-image-is-fully-loaded" or the image_data will be nothing but black.
var image_data = hctx.getImageData(0,0,1000,1000);
var rgba_byte_array = image_data.data; // image_data.data.length = 4000000
var loop = setInterval(loop,1000/30);
function loop()
{ ...
The code works with the alert, because it causes the required "break" for loading the image. I wish not to use JQuery nor Ajax.
Here I use imageObj.onload directly at drawing on canvas. Probably not the right way?
Thanks in advance for the feedback and the solution.
You should put
var image_data = hctx.getImageData(0,0,1000,1000);
var rgba_byte_array = image_data.data; // image_data.data.length = 4000000
var loop = setInterval(loop,1000/30);
inside imageObj.onload function

why aren't my images showing up

Hi I'm trying to learn how to use the EaselJS libraries, eventually combining with some of the EXTJS libs butt I'm having trouble putting all my code in the .Js files. My js file looks like this
var democanvas = document.createElement('canvas');
document.body.appendChild(democanvas);
democanvas.height = "400";
democanvas.width = "600";
function init() {
var canvas = document.getElementById("democanvas");
var stage = new createjs.Stage('canvas');
var im = new createjs.Bitmap("dbz.jpg");
// im.regX - im.image.width *.2;
// im.regY - im.image.height *.2;
stage.addChild(im);
stage.update();
im.addEventListener("click", function(){
var seed = new createjs.Bitmap("seed.jpg");
seed.alpha = 0.5;
seed.x = window.event.clientX;
seed.y = window.event.clientY;
stage.addChild(seed);
stage.update();
}); //end seed evenlistener */
} //end functin init()
this doesn't work, but if I comment out the whole document.createElement('canvas') section and I apply
<body onLoad="init();">
<canvas id="demoCanvas" width="1000" height="1000">
alternate content
</canvas>
to my index.html file It will start working :( I included the .js within the body tag of te index html
Edit:::::::::::::::::::::: this is my current code, still not showing anything unless I add the canvas to the html page :(
window.onload = function (){
var demoCanvas = document.createElement('canvas');
//document.body.appendChild(democanvas);
demoCanvas.height = "400";
demoCanvas.width = "600";
}
var stage;
function init() {
stage = new createjs.Stage("demoCanvas");
var text = new createjs.Text("Hello World", "bold 86px Arial", "#ff7700");
stage.addChild(text);
stage.update();
}
init();
Another thing - since you are using image paths, and not fully loaded images as Bitmaps sources, its possible the images are not ready when you update the stage. You can either put onload handlers on your image(s) to update the stage, or preload them first.
var image = new Image();
image.onload = handleLoad;
image.src = "src.jpg";
function handleLoad(event) { stage.update(); }
// You can also use the Bitmap
var bitmap = new createjs.Bitmap("src.jpg");
bitmap.image.onload = handleLoad;
You can also tick the stage to update it constantly. This is a quick way to see if thats the problem.
createjs.Ticker.addEventListener("tick", stage);
// OR
createjs.Ticker.on("tick", stage);
try the below :
document.body.onload = function(){
var democanvas = document.createElement('canvas');
document.body.appendChild(democanvas);
democanvas.height = "400";
democanvas.width = "600";
function init() {
var canvas = document.getElementById("democanvas");
var stage = new createjs.Stage('canvas');
var im = new createjs.Bitmap("dbz.jpg");
// im.regX - im.image.width *.2;
// im.regY - im.image.height *.2;
stage.addChild(im);
stage.update();
im.addEventListener("click", function(){
var seed = new createjs.Bitmap("seed.jpg");
seed.alpha = 0.5;
seed.x = window.event.clientX;
seed.y = window.event.clientY;
stage.addChild(seed);
stage.update();
}); //end seed evenlistener */
} //end functin init()
init();
}
Firstly you need to use the console of your navigator to see javascript's errors before any question.
You will see this error : Uncaught TypeError: Cannot call method 'appendChild' of null
That because you load document.body.appendChild(democanvas); before the html is load so your document.body is null.
This is the way:
function init() {
var democanvas = document.createElement('canvas');
document.body.appendChild(democanvas);
democanvas.height = "400";
democanvas.width = "600";
var canvas = document.getElementById("democanvas");
var stage = new createjs.Stage('canvas');
var im = new createjs.Bitmap("dbz.jpg");
// im.regX - im.image.width *.2;
// im.regY - im.image.height *.2;
stage.addChild(im);
stage.update();
im.addEventListener("click", function(){
var seed = new createjs.Bitmap("seed.jpg");
seed.alpha = 0.5;
seed.x = window.event.clientX;
seed.y = window.event.clientY;
stage.addChild(seed);
stage.update();
}); //end seed evenlistener */
} //end functin init()
I had the same problem and I solved it by using a preloader.
You can use the PreloadJS preloader like this:
var preloader = new createjs.LoadQueue(true);
preloader.addEventListener("complete",this.handleComplete.bind(this));
var manifest = [
{src:"./images/yourIMAGE.PNG"},
//another image
];

a variable is not defined but i initialized it before

I write a client with nodejs and javascript.when i debug the code the console says that the X1 variable of coordinate is not defined, but i initialized it before.who can explain it for me?
the variable located at "localPlayer = new Player(X1, Y1);"
var canvas = document.getElementById("painting");
var socket; //Socket connection
var localPlayer, remotePlayers; // local and remote players
var context2D = canvas.getContext("2d");
var lifecount = 3; // frogger has three life values
var score = 0; // when frogger accross a line successfully it will get 10 points
//initialized the coordinates
function initcoordinates(){
var pipe0X=0,pipe0Y=110;
var spider1X= 0,spider1Y=140;
var spider2X= 0,spider2Y=230;
var X1=300,Y1=450; // frogger's ordinary coordinate
var pipe1X=0,pipe1Y=170;
var pipe2X= 0,pipe2Y=200;
var rocketX = 0,rocketY=300;
var carX = 0, carY =330;
var wheelX= 0,wheelY=360;
var car1X= 0, car1Y=390;
var car2X= 0, car2Y=420;
};
function initimage(){
var picpipe0 = new Image();
var pic1=new Image();
var picpipe1 = new Image(); // pipe image
var picpipe2 = new Image();
var spider1 = new Image();
var spider2 = new Image();
var gresp1 = new Image();
var gresp2 = new Image();
var rocket = new Image();
var car = new Image();
var wheel = new Image();
var car1 = new Image();
var car2 = new Image();
//load image
picpipe0.src = "pipe.jpg";
pic1.src = "qingwa.jpg";
picpipe1.src = "pipe.jpg";
picpipe2.src = "pipe.jpg";
spider1.src="spider.jpg";
spider2.src="spider.jpg";
gresp1.src = "gresp.jpg";
gresp2.src = "gresp.jpg";
rocket.src = "rocket.jpg";
car.src = "car.jpg";
wheel.src = "wheel.jpg";
car1.src = "car1.jpg";
car2.src = "car2.jpg";
};
/**************************************************
** GAME INITIALISATION
**************************************************/
function init(){
initcoordinates();
initimage();
// Initialise socket connection
socket = io.connect("http://localhost", {port: 8000, transports: ["websocket"]});
// Initialise remote players array
remotePlayers = [];
// Initialise the local player
localPlayer = new Player(X1, Y1);
// Start listening for events
setEventHandlers();
}
Your X1 variable is locally scoped in the initcoordinates function, it can't be accessed by the init function. Not only the X1 variable is local, but ALL the coordinates you're setting in the initcoordinates function will only be visible inside this function. I suggest you to declare these variables outside, in an immediate function surrounding the others, like this:
(function(){
var X1;
function initcoordinates(){
X1 = ...
}
function init(){
//do something with the X1 variable here...
}
})();
This way, all your functions will share the access to the variables declared in the scope of your immediate function.

Categories