HTML5 Canvas rendering oddly - javascript

I'm in the process of learning HTML5 (and OO Javascript) and am trying to make a simple game engine but rendering to canvas works under very odd conditions. Here is a link to the page and here is my index.html:
<html>
<head>
<script type="text/javascript">
function load()
{
var game = new Game();
game.start();
}
</script>
<title>Game</title>
<style>
canvas
{
outline:0;
border:1px solid #000;
margin-left: auto;
margin-right: auto;
}
</style>
</head>
<body onload="load()">
<canvas id='c'></canvas>
<script src="classes/Tuple.js"></script>
<script src="classes/Rect.js"></script>
<script src="classes/Sprite.js"></script>
<script src="classes/Game.js"></script>
</body>
</html>
When first loaded, it will give an NS_ERROR_DOM_TYPE_MISMATCH_ERR Exception in Firefox 11.0 and a TypeError Exception in Chrome 18.0. To make it work:
Firefox 11.0
select the URL in the address bar and manually hit enter OR
click the refresh button OR
press F5.
Chrome 18.0
select the URL in the address bar and manually hit enter OR
click the refresh button OR
press F5 OR
press Shift/Ctrl + F5.
What I suspect - Just a guess but it seems like one or more of the .js files is not available/ready by the time it is called during the first page load. Having stepped through it a couple of times in Firebug it seems that the sprite images never get loaded on the first page request.
Perhaps some of the .js files are still being downloaded as the instantiation to Game() is being made, then cached, and are only all available by the second page load?
Any ideas? I'd be grateful for your take on it, thanks!

I copied your files locally and did some testing. It looks to me like it's not your JavaScript files that are unavailable, but your sprite.
You're not loading the PNG until you call Game.start. When you do:
roadSpritesheetImage.src = "assets/sprites/player/playerSpriteSheet.png";
This begins an asynchronous download of the image. The rest of the code is executed before the image has fully loaded, so when you're slicing the image, you're slicing it as if the src attribute were null.
This is why you're able to hit refresh and everything works as expected... the image is cached.
You can sort of preempt the loading of your sprite by adding an image tag just before the canvas:
<img src="assets/sprites/player/playerSpriteSheet.png" style="display:none;" />
This would work because the body load event isn't fired until content (including images) is fully loaded (I believe, I'd have to look this up). Then, if you assign this image to img.src, you will be referencing the cached image.
Alternatively, you could bind the rest of the game functionality to img.onload. For example:
self.loadSprites = function()
{
var roadSpritesheetImage = new Image();
roadSpritesheetImage.onload = function() {
self.entities.push(new Sprite("testTile",
roadSpritesheetImage,
new Tuple(16, 16),
new Rect(0, 0, 32, 16)));
self.run();
};
roadSpritesheetImage.src = "assets/sprites/player/playerSpriteSheet.png";
};
self.run = function() {
var drawSuccessful = false;
drawSuccessful = self.entities[0].draw(self.context);
self.entities[0].nextFrame();
//if we managed to draw the Sprite successfully without any raised exceptions
if(drawSuccessful) {
setTimeout(self.run, 300);
} else { alert("stopping execution of the game."); }
};
self.start = function()
{
self.loadSprites();
};
Doing this is a bit cleaner and it would guarantee you don't have any race conditions with your resources.
I had a similar issue with a jQuery plugin I created to draw an N-puzzle from a source image. I found this MDN documentation extremely useful at the time, although I ended up using sliced divs instead of a canvas.

Related

How to initialise SoundJS for IOS 9

We've been using the CreateJS suite for a while now, but have just realised that our audio is not working on IOS9. Unfortunately we only have one IOS9 test device, running IOS9.2.4, but are getting mixed results with audio playback.
The rough process I'm using is;
Preload all assets (scripts/images/audio) via PreloadJS
Construct an initial splash screen in EaselJS, including a start button
Continue with the main content
It would be advantageous to be able to preload all audio before presenting that splash screen. The splash screen was added initially to allow audio to play on mobile Safari, with an empty sound played on click. This does of course work for IOS7/8, but not for 9.
I've created this test case on codepen as an attempt to track down the issue and try some options.
Codepen sample
HTML
<p id="status">Hello World</p>
<canvas id="canvas" width="200" height="200"></canvas>
JS
var canvas, stage, rect;
function init() {
canvas = document.getElementById('canvas');
canvas.style.background = "rgb(10,10,30)";
stage = new createjs.Stage("canvas");
createjs.Touch.enable(stage);
rect = new createjs.Shape();
rect.graphics.f("#f00").dr(50,75,100, 50);
rect.on("mousedown", handleStart, null, true);
rect.on("touchend", handleStart, null, true);
//rect.on("click", handleStart, null, true);
stage.addChild(rect);
stage.update();
$('#status').text("Touch to Start");
createjs.Sound.initializeDefaultPlugins();
//createjs.Sound.alternateExtensions = ["ogg"];
createjs.Sound.registerSound("https://www.freesound.org/data/previews/66/66136_606715-lq.mp3", "ding1");
}
function handleStart(event) {
createjs.WebAudioPlugin.playEmptySound();
$('#status').text("Touch to Play");
rect.graphics._fill.style = '#0f0';
rect.removeAllEventListeners();
rect.on('click', handlePlay);
stage.update();
}
function handlePlay(){
createjs.Sound.play("ding1");
$('#status').text("Playing");
}
init();
Apologies for the lack of ogg version, was struggling to get test files to load x-domain.
With this, audio partially works for us on IOS9. If we leave clicking the red rectangle (figure start button) and leave it ~20 seconds, then click the green button no audio plays. If we click it immediately, audio plays fine.
I have been reviewing this bug/thread and attempting to follow Grant's suggestions. I gather SoundJS v0.6.2 now automatically attempts to play the empty sound appropriate when plugins are initialized, however moving the initializeDefaultPlugins and registerSounds calls into the handleStart function appears to make no difference. If I'm understanding the issue correctly, calling the WebAudioPlugin.playEmptySound method should be sufficient?
Have also been looking at the event binding, trying mousedown/touchend instead of click, but the result is the same with the 20 second wait. Event also appears to fire twice, although I could probably dig deeper into that if I could get it to work correctly.
I'm aware of the Mobile Safe Approach article aimed at this issue, but the need for a namespace at this level would mean a substantial rewrite of our existing content. Could someone perhaps advise if it is completely necessary to take this approach? I'm under the impression it should be feasible by correctly playing some empty audio within that initial handler.
Can't actually get the main project to this point, but if I can get a working example perhaps I'll be a step closer.
Any thoughts would be appreciated!
The Mobile-safe tutorial is not really relevant anymore since the updates in 0.6.2. It will likely be updated or removed in the near future.
You should never need to initializeDefaultPlugins(), unless you want to act on the result (ie, check the activePlugin before doing something). This method fires automatically the first time you try and register a sound.
The playEmptySound is also no longer necessary. SoundJS will listen for the first document mousedown/click, and automatically do this in the background.
touch events are not directly propagated from the EaselJS stage, but are instead turned into mouse events (touchstart=mousedown, touchmove=mousemove, touchend=pressup/click)
Based on this, you should be able to play sound once anywhere in the document has been clicked, regardless of whether you listen for it or not.
That is not to say that there isn't a bug, just that the steps you are taking shouldn't be necessary. I did some testing, and it appears to work in iOS9. Here is a simplified fiddle.
https://jsfiddle.net/lannymcnie/b4k19fwc/ (link updated Dec 3, 2018)

How to refresh image source only if new image is actually available?

<!--WunderGroundRadar-->
<script type = "text/javascript">
setInterval(function refreshRadar() {
   document.getElementById("content14").src = "http://api.wunderground.com/api/MyAPIkey/animatedradar/q/autoip.gif?&radius=90&num=15&delay=20&width=430&height=500&smooth=1&newmaps=1&interval=15&rainsnow=1"
  }, 900000);
</script>
I use the code above to refresh a weather radar .gif image on my website about every 15 minutes. This normally works great, but sometimes when the refresh takes place the image is broken from it's source and my site has a broken image icon until the next refresh takes place approx. 15 minutes later. I would like to set this up so that if the requested image is broken or not available at the time that the refresh function runs, I keep the image that is already loaded instead of replacing it with a broken image icon. I am willing to use any javascript or Jquery that might achieve this, but I am a novice programmer, so if you could break down any intricate code that would be much appreciated. Thanks!
You can try something like this
<script type = "text/javascript">
setInterval(function refreshRadar() {
img = new Image();
img.onload = function(){
document.getElementById("content14").src = img.src;
};
img.src = "http://api.wunderground.com/api/MyAPIkey/animatedradar/q/autoip.gif?&radius=90&num=15&delay=20&width=430&height=500&smooth=1&newmaps=1&interval=15&rainsnow=1"
}, 900000);
</script>
it attempts to load source to a temporary image and only on successful load assings source to "content14"

GIF Image Stops when "document.location.href"

I have this function in javascript :
function loadPage (url){
showLoadPageGif(); // visibility On
document.location.href = getPath + "/" + url ;
}
When I use this function , GIF image is displayed in the screen but not working .
someone has fought before, with this problem ? thnx
i recently ran into this issue using animated SVGs as background-images in pseudo elements. I purposefully put in a large delay on my webserver so i could stay on the current page after window.location = url; It was weird that all other CSS animations and hovers still worked, but the SVG cog just stuck.
After some playing around i found that the animations continued to run if, instead of changing window.location, i submitted a GET form.
var url;
//load & setup loading animation
//then generate and submit form with a slight delay
setTimeout(function(){
var new_form;
new_form = document.createElement('form');
new_form.method = 'GET';
new_form.action = url;
document.body.appendChild(new_form);
new_form.submit();
}, 100)
tested on safari 5.1, firefox 24, chrome 32
I assume you mean "GIF animation stops".
This is the correct behavior. Since you go to a new page, all resources for the old page are freed. This of course includes the GIF itself.
You don't "see" this happening because the browser doesn't waste any time rendering a blank page when you assign location.href.
What you need to do is use an AJAX to request the new page and then replace the whole DOM with the new one in the success handler.
There is a bug in IE6 which stops the animations when you start an AJAX request; to fix that, just assign the src attribute of the image again (i.e. img.src = img.src;) to restart them.
Which browser you're using ? I needed to do the same one time if you're using IE just do this :
var loadingFigure = $('#myImage');
var html = loadingFigure.html();
window.location.href = 'myImage';
loadingFigure.html(html);
For firefox is more complicated you need to use an iframe and do something like this :
<iframe id="myIframe" src="/images/busy.gif" scrolling="no" frameborder="0"></iframe>
$('#myIframe').attr('src', '/images/busy.gif');
window.location.href = 'mylocation'
$('#myIframe').attr('src', '/images/busy.gif');

how to remove delay in image loading in html?

I create a web page and put an img tag on this page. the img.src is the url of the image from the network IP camera. It works but the stream I get have delays. I understand this delay is because I load the image and loading image takes some time. my question is how can I minize these delay. I do the following;
<script language="Javascript">
x = document.getElementById("stream");
intervalID = setInterval(LoadImage, 0);
function LoadImage()
{
x = document.getElementById("stream");
x.src = "http://IP:PORT/jpg/image.jpg";
}
</script>
<img id="stream"
width="640" height="480"
alt="Press reload if no video displays"
border="0" style="cursor:crosshair; border:medium; border:thick" />
<button type="button" id="btnStartLive" onclick="onStartLiveBtnClick()">Start Live</button>
I've just found your question in the unanswered section and decided to give it a go. The following script creates an internal <img> tag (with new Image()), assigns the necessary attributes, then sets an onload "event handler" attribute, which checks when the image loaded. When that function is called, the #stream is replaced by the new internal image tag.
In case the #stream is not directly inside the body tag (i.e. inside another element like a <div>), edit streamParentElement to point to the image's parent element.
I added a ?nocache query parameter to the string, because while I was testing the code, I found out that the image tag was changing but the visible image stayed the same. I also added a loadDelay, because the images on my client were loading too fast, and it got to the point where it crashed my browser. I advise you to not lower that value below 50. Live demonstration of this code here
<script language="Javascript">
var streamParentElement = document.body, loadDelay = 200;
setTimeout(MakeImage,1);
function MakeImage(){
var img = new Image();
img.src = "http://IP:PORT/jpg/image.jpg?nocahce="+new Date().getTime()+Math.random();
img.width = 640;
img.height = 480;
img.style.border = 0;
img.style.cursor = 'crosshair';
img.id = 'stream';
img.onload = function(){
var stream = document.getElementById("stream");
streamParentElement.insertBefore(img,stream);
stream.outerHTML = '';
setTimeout(MakeImage, loadDelay);
};
}
</script>
<img id="stream" alt="Press reload if no video displays" />
create your html page. eg:
<html>
<head>
<title>
Some Page
</title>
</link rel="stylesheet" href="path to your css file"/>
<script type="text/javascript" src="path to you javasctipt file"></script>
</head>
<body>
<h1 onClick="javascript:someFunction()">
Click here
</h1>
</body>
</html>
you can then create many other "someFunction" functions. They all just reference the AJAX function.this is just to make typing a little less...
The easiest ajax way:
var path;
var div;
var xmlhttp = new XMLHttpRequest();
function someFunction()
{
path = "path to another html file";
div = "the name of the div tag's content you want to change eg. content";
AJAX(path, div);
}
function AJAX(path, div)
{
xmlhttp.open("GET", path, false);
xmlhttp.send();
if (xmlhttp.readyState == 4)
{
document.getElementById(div).innerHTML = xmlhttp.responseText;
}
}
now just include the image in the html file.
ajax allows you to change just the content of the div you gave it, without reloading the whole page.
I would try putting your images into photoshop and making the resolution 72 or less. Also if you save the images as a GIFs they should be much smaller.
maybe handle the image loading in an outside script that runs faster than a web page refreshes, then embed it? like a "videoloader.js" so that it can load separately and not have to wait on the html page to load.
<script src="videoloader.js"></script>
you could also convert the images shown on the fly into lesser quality jpgs using javascript
see if this helps:
Load lower quality image if higher one inst available

Changing <img src="XXX" />, js event when new image has finished loading?

I have a photo gallery web page where a single <img src="XXX" /> element's src is changed (on a click) with JavaScript to show the next image—a poor man's ajax I guess. Works great on faster connections when the new image appears almost immediately. Even if it takes a few seconds to load, every browser I've tested it on keeps the old image in place until the new one is completely loaded.
It's a little confusing waiting those few seconds on a slow connection, though, and I'm wondering if there's some JavaScript event that fires when the new image is done loading, allowing me to put a little working... animated gif or something up in the meantime.
I know I could use AJAX for real (I'm using jQuery already), but this is such a nice and simple solution. Besides this lag, is there any other reason I should stay away from this approach to changing images?
You can set up a handler on the "load" event.
$('img.whatever')
.load(function() { /* do stuff */ })
.attr('src', newURL);
Actually I guess you'd want to do this with "live()":
$('img.reloadable').live('load', function() { $(this).show(); });
// ...
$('img#someId').hide().attr('src', newURL);
edit — whoa, where did that year go? Well, it turns out that one problem with that "live" approach I typed in way back when is that the "load" event does not bubble. Now what you can do, however, is leverage the way that "Image" objects (as opposed to <img> DOM elements) behave. Basically, the function that changes the URL can use an "Image" element as the place to keep the handler. The code that changes the actual "src" attribute of the real <img> tag would then also update the "src" of the "Image" object instance. The browser will only really load the image once (assuming cache control is all cool), but the browser will still call the "onload" handler of the "Image":
(function() {
var imageObj = new Image();
imageObj.onload = function() {
// code to run when image loads from server
};
$('#hypotheticalButton').click(function() {
$('#imgToUpdate').attr('src', newURL);
imageObj.src = newURL;
});
})();
You just just preload the images with jQuery so that way when the user clicks, the next image is already loaded and there shouldn't be a delay...that is unless the user goes to your page, and starts clicking on the image before they are loaded.
http://engineeredweb.com/blog/09/12/preloading-images-jquery-and-javascript
var slideimg = $('#slideimage');
slideimg.click(function(){
var img = new Image();
var url = 'url_to_next_image.jpg';
$(img).bind('load',function(){
$('#loading').hide();
slideimg.attr('src',url);
}).attr('src',url);
$('#loading').show();
});
This should work even with IE's crazy cache handling.

Categories