Set an Image object as a div background image using javascript - javascript

I want to load 4 images from background showing a load bar to the client
and when the images will be downloaded i want to set them as background images to 4 div blocks.
I am looking for something like this.
var myImages = new Array();
for(var i = 0; i < 4; i++)
myImages[i] = new Image();
//load images using the src attribute
//and execute an on load event function where to do something like this.
var div0 = document.getElementById('theDivId');
div0.style.backgroundImage = myImage[index];
Is there any way to set a background image using an Image javascript object?

You can do something close to what you had. You don't set an image background to be an image object, but you can get the .src attribute from the image object and apply that to the backgroundImage. Once the image object has successfully loaded, the image will be cached by the browser so when you set the .src on any other object, the image will load quickly. You could use this type of code:
var imgSrcs = [...]; // array of URLs
var myImages = [], img;
for (var i = 0; i < 4; i++) {
img = new Image();
img.onload = function() {
// decide which object on the page to load this image into
// this part of the code is missing because you haven't explained how you
// want it to work
var div0 = document.getElementById('theDivId');
div0.style.backgroundImage = "url(" + this.src + ")";
};
img.src = imgSrcs[i];
myImages[i] = img;
}
The missing part of this code is deciding which objects on the page to load which image into when the image loads successfully as your example stood, you were just loading each one into the same page object as soon as they all loaded which probably isn't what you want. As I don't really know what you wanted and you didn't specify, I can't fill in that part of the code.
One thing to watch out for when using the .onload event with images is you have to set your .onload handler before you set the .src attribute. If you don't, you may miss the .onload event if the image is already cached (and thus it loads immediately).

This way, the image shows up instantly all in one once it's loaded rather than line by line.
function setBackgroundImage(){
imageIsLoaded(myURL).then(function(value) {
doc.querySelector("body > main").style.backgroundImage = "url(" + myURL + ")";
}
}
function imageIsLoaded(url){
return new Promise(function(resolve, reject){
var img = new Image();
try {
img.addEventListener('load', function() {
resolve (true);
}, false);
img.addEventListener('error', function() {
resolve (false);
}, false);
}
catch(error) {
resolve (false);
}
img.src = url;
});
}

Related

How to preload images during a looped array for background images

I've written a simple loop that cycles through a series of images in an array into the background-image property of an element. The problem is that due to the fact that the images are loading, the animation is going haywire when everything is initially loading. I'm trying to set up a preloading workflow where:
the entire loop is blocked by waiting until the first image is fully loaded
every time a new image is fully preloaded, it begins preloading the following image
the preloading must stop when the array is over and use cached images so it's easy on the browser and doesnt just keep loading the same array on images over and over eternally.
Any help?
http://codepen.io/jeremypbeasley/pen/JoZzyo?editors=001
var photoSet = [
"https://farm6.staticflickr.com/5475/9790841974_182a06590a_o.jpg",
"https://farm3.staticflickr.com/2840/9042399407_bf04388aca_o.jpg",
"https://farm6.staticflickr.com/5504/14634417581_626ea1a835_o.jpg"
];
var p = photoSet.length;
console.log(p);
var i = 1;
function loopPhotos() {
setTimeout(function() {
$('div').css({'background-image': 'url(' + photoSet[i] + ')',});
i++;
console.log(i);
// call the next indexed image and begin to preload it
var img = new Image();
img.src = photoSet[i];
if (i >= p) {
i = 0;
// stop preloading images, somehow used images that are cached so the browser isn't working eternally reloading the same X number of photos.
}
loopPhotos();
}, 2000)
}
$(document).ready(function() {
// load first image
var firstImg = new Image();
firstImg.src = photoSet[0];
// when first image is loaded, apply it to background and begin looping
if (firstImg.complete) {
$('div').css({'background-image': 'url(' + firstImg.src + ')',});
loopPhotos();
console.log('first image loaded!');
}
});
This will do it
var photoSet = [
"https://farm6.staticflickr.com/5475/9790841974_182a06590a_o.jpg",
"https://farm3.staticflickr.com/2840/9042399407_bf04388aca_o.jpg",
"https://farm6.staticflickr.com/5504/14634417581_626ea1a835_o.jpg"
];
function preloadImageAndAct(src, action){
var img = new Image();
img.onload = action;
img.src = src;
}
function showImage( src ){
$('div').css({
'background-image': 'url(' + src + ')',
opacity: 1
});
}
var nextImage = 0;
function loopPhotos() {
console.log('Preload and show image #', nextImage);
var nextSrc = photoSet[nextImage];
preloadImageAndAct( nextSrc, function(){
showImage( nextSrc );
setTimeout( function() {
nextImage++;
nextImage %= photoSet.length;
loopPhotos();
}, 2000);
});
}
$(document).ready(function() {
loopPhotos();
});
Demo at http://codepen.io/gpetrioli/pen/rarPay
Keep in mind that you cannot transition the background-image. If you want transition for the change of images you need to either use two elements or fade the element out / change src / fade the element in.
AS for the caching, once they have been loaded once they are automatically cached by the browser so there should be no issue with that.

Using canvas to create desktop notification images, only one image works from background page

I'm having an issue while using canvas in a background page to create data URLs for desktop notifications' images.
I want to use the "image" notifications which require a 3:2 ratio to display properly. The images I want to use (from hulu.com) are a different ratio, so I decided to use the canvas element to create the corresponding data URL off of these images so that the ratio is correct. It kind of works in theory, but…
…I'm having issues if I'm creating more than one canvas/notification in the background page. One image is created properly, but the rest comes out empty.
Confusingly, opening the same background page in a new tab (i.e. exact same code) makes everything works just fine: all the notifications are created with the images loaded from hulu.com. Also, just changing the dimensions from 360x240 to 300x200 makes it work. Finally, though they're similar computers with the same Chrome version (34.0.1847.116), it works without modification at work while it doesn't on my own laptop.
I made a test extension available at the bottom of this post. Basically, it only has a generated background page. The code for that page is this:
var images = ["http://ib2.huluim.com/video/60376901?size=290x160&img=1",
"http://ib2.huluim.com/video/60366793?size=290x160&img=1",
"http://ib4.huluim.com/video/60372951?size=290x160&img=1",
"http://ib1.huluim.com/video/60365336?size=290x160&img=1",
"http://ib3.huluim.com/video/60376290?size=290x160&img=1",
"http://ib4.huluim.com/video/60377231?size=290x160&img=1",
"http://ib4.huluim.com/video/60312203?size=290x160&img=1",
"http://ib1.huluim.com/video/60376972?size=290x160&img=1",
"http://ib4.huluim.com/video/60376971?size=290x160&img=1",
"http://ib1.huluim.com/video/60376616?size=290x160&img=1"];
for (var i = 0; i < 10; i++) {
getDataURL(i);
}
/*
* Gets the data URL for an image URL
*/
function getDataURL(i) {
var img = new Image();
img.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = 360;
canvas.height = 240;
var ctx = canvas.getContext('2d');
ctx.drawImage(this, 0, 0);
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect (10, 10, 55, 50);
var dataURL = canvas.toDataURL('image/png');
chrome.notifications.create('', {
type: 'image',
iconUrl: 'logo_128x128.png',
title: String(i),
message: 'message',
imageUrl: dataURL
}, function(id) {});
}
//img.src = chrome.extension.getURL('logo_128x128.png');;
img.src = images[i];
}
The commented out line for img.src = ... is a test where it loads a local file instead of a remote one. In that case, all the images are created.
The red rectangle added to the canvas is to show that it's not just the remote image that is an issue: the whole resulting canvas is empty, without any red rectangle.
If you download and add the test extension below, you should get 10 notifications but only one with an image.
Then, to open the background page in a new tab, you can inspect the background page, type this in the console:
chrome.extension.getURL('_generated_background_page.html')
and right-click the URL, and click "Open in a new Tab" (or window). Once open you should get 10 notifications that look fine.
Any idea of what is going on? I haven't been able to find any kind of limitations for background pages relevant to that. Any help would be appreciated, because this has been driving me crazy!
Files available here: https://www.dropbox.com/s/ejbh6wq0qixb7a8/canvastest.zip
edit: based on #GameAlchemist's comment, I also tried the following: same getDataURL method, but the loop wrapped inside an onload for the logo:
function loop() {
for (var i = 0; i < 10; i++) {
getDataURL(i);
}
}
var logo = new Image();
logo.onload = function () {
loop();
}
logo.src = chrome.extension.getURL('logo_128x128.png');
Remember that the create() method is asynchronous and you should use a callback with. The callback can invoke next image fetching.
I would suggest doing this in two steps:
Load all the images first
Process the image queue
The reason is that you can utilize the asynchronous image loading better this way instead of chaining the callbacks which would force you to load one and one image.
For example:
Image loader
var urls = ["http://ib2.huluim.com/video/60376901?size=290x160&img=1",
"http://ib2.huluim.com/video/60366793?size=290x160&img=1",
"http://ib4.huluim.com/video/60372951?size=290x160&img=1",
"http://ib1.huluim.com/video/60365336?size=290x160&img=1",
"http://ib3.huluim.com/video/60376290?size=290x160&img=1",
"http://ib4.huluim.com/video/60377231?size=290x160&img=1",
"http://ib4.huluim.com/video/60312203?size=290x160&img=1",
"http://ib1.huluim.com/video/60376972?size=290x160&img=1",
"http://ib4.huluim.com/video/60376971?size=290x160&img=1",
"http://ib1.huluim.com/video/60376616?size=290x160&img=1"];
var images = [], // store image objects
count = urls.length; // for loader
for (var i = 0; i < urls.length; i++) {
var img = new Image; // create image
img.onload = loader; // share loader handler
img.src = urls[i]; // start loading
images.push(img); // push image object in array
}
function loader() {
count--;
if (count === 0) process(); // all loaded, start processing
}
//TODO need error handling here as well
Fiddle with concept code for loader
Processing
Now the processing can be isolated from the loading:
function process() {
// share a single canvas (use clearRect() later if needed)
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
current = 0;
canvas.width = 360;
canvas.height = 240;
createImage(); // invoke processing for first image
function createImage() {
ctx.drawImage(images[current], 0, 0); // draw current image
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect (10, 10, 55, 50);
chrome.notifications.create('', {
type : 'image',
iconUrl : 'logo_128x128.png',
title : String(i),
message : 'message',
imageUrl: canvas.toDataURL() // png is default
},
function(id) { // use callback
current++; // next in queue
if (current < images.length) {
createImage(); // call again if more images
}
else {
done(); // we're done -> continue to done()
}
});
}
}
Disclaimer: I don't have a test environment to test Chrome extensions so typos/errors may be present.
Hope this helps!

How to preload images

I'm trying to preload images on my web page. I've seen a lot of discussions about it and most of them suggest to create an Image object then edit the src attribute. However this doesn't work on the latest versions of Chrome and Firefox. The request is marked as "pending" until the image is actually shown on the page and then I can notice a little delay before the image to be shown. Even creating an actual img tag on the page (with display:none) doesn't work until the image is shown. And finally when I try the following code, only the last image of the loop is actually loaded
var img = document.getElementById('some_visible_image');
for(var i=1;i<5;i++)
for(var j=1;j<3;j++){
img.src = 'images/'+i+'_'+j+'_green.png';
img.src = 'images/'+i+'_'+j+'_orange.png';
img.src = 'images/'+i+'_'+j+'_red.png';
}
So how can I reduce the loading time of the images (without using large sprites)?
You need to create instance for every image
// redirect after all the images are preloaded
function redirect() {
location.href = "yourtargetpage.html";
}
// should solve the first-time-load problem
var loads = 0;
function loaded() {
// the total number of images needed to load
if(++loads==42) redirect();
}
// if all the images aren't loaded in 3 seconds, don't wait further
setTimeout(redirect, 3000);
for(var i=1;i<5;i++)
for(var j=1;j<3;j++){
var img = new Image();
img.src = 'images/'+i+'_'+j+'_green.png';
if(img.complete) loaded(); // if cached, onload isn't fired sometimes
else img.onload = loaded; // fires for the first time the page loads
}
or the src is overwritten before the image has a chance to load.
To show your images immediately after the first load, you may run this script on a different page, wait until every image
I found the solution, thanks to Jan Turoň's answer. Here is my code :
for(var i=1;i<=5;i++)
for(var j=1;j<=3;j++){
var img = new Image();
img.src = 'images/'+i+'_'+j+'_green.png';
var img = new Image();
img.src = 'images/'+i+'_'+j+'_orange.png';
var img = new Image();
img.src = 'images/'+i+'_'+j+'_red.png';
var img = new Image();
img.src = 'images/'+i+'_'+j+'_grey.png';
}
Try visibility:hidden; instead of display:none;

Canvas load image before anything starts?

When I play my game and click space I show a pause screen with info and images. However the images dont show for like 5 seconds after the page is loaded. I guess this is because they are still loading. How can I prevent canvas from running until the images are loaded?
http://www.taffatech.com/Snake.html
click space straight away.
then click it again, wait 6-10 seconds and press it again.
this is the code for showing the images:
if(level == 1)
{
var img = new Image();
img.src = 'egg.png';
con.drawImage(img,350,40);
}
else if(level ==2)
{
var img = new Image();
img.src = 'baby.png';
con.drawImage(img,350,40);
}
else if(level ==3)
{
var img = new Image();
img.src = 'adult.png';
con.drawImage(img,350,40);
}
else
{
var img = new Image();
img.src = 'ultimate.png';
con.drawImage(img,350,40);
}
You just need to delay the execution of other scripts until the image you desire has been loaded. In your JavaScript, whenever you want to preload your image, you can use the following code as a guideline:
function onImageLoad(e) {
// Put code here to start your canvas business.
};
var image = new Image();
image.addEventListener('load', onImageLoad);
image.src = 'the/path/to/your/image.whatever'
Your onImageLoad function could render your image to the canvas (so the image load happens when you press pause), or you could have this script execute at the beginning and the function simply stores the image into a global variable. Up to you!
Hope this helps :)
You can keep all the image paths in an array and load all the images before starting
var imageObjects = [];
function loadImages(images, onComplete) {
var loaded = 0;
function onLoad() {
loaded++;
if (loaded == images.length) {
onComplete();
}
}
for (var i = 0; i < images.length; i++) {
var img = new Image();
img.addEventListener("load", onLoad);
img.src = images[i];
imageObjects.push(img);
}
}
function init() {
alert("start game");
// use imageObjects which will contain loaded images
}
loadImages(["egg.png", "baby.png", "adult.png", "ultimate.png"], init);
waitForImages jQuery plugin
GitHub repository.
$('selector').waitForImages(function() {
alert('All images are loaded.');
});

NS_ERROR_NOT_AVAILABLE: Component is not available

I have a problem. I am trying to draw an image onto a canvas. The image is not from the HTML page, but on a file. Here is the code i use:
var img = new Image();
img.src = "/images/logo.jpg";
this._canvas.drawImage(img, 300, 300);// this is line 14
now, here's the problem. This does not seem to work on Firefox and IE10 (I haven't tested yet on other browsers). On Firefox (21) I get:
[19:09:02.976] NS_ERROR_NOT_AVAILABLE: Component is not available # file:///D:/Watermellon/scripts/base-classes.js:14
and on IE10 i get:
SCRIPT16389: Unspecified error.
base-classes.js, line 14 character 13
The files and their directories are:
root/index.html
root/scripts/base-classes.js
root/images/logo.jpg
Now when I change the img.src to a URL (an image from another site) everything works fine, the image draws itself after a delay(for it's get from the url). What am I doing wrong?
I'm guessing the problem is that the image isn't loaded yet before you attempt to use it. Try this:
var img = new Image();
img.onload = function () {
this._canvas.drawImage(img, 300, 300);// this is line 14
};
img.src = "images/logo.jpg";
The src property is set after binding the event because a cached image's load event fires immediately (which is a common problem in IE).
And according to your structure, the path to the image would probably be images/logo.jpg (removing the first /)
You need to wait for the image to load before attempting to draw it into a canvas:
var img = new Image();
img.src = "/images/logo.jpg";
img.onload = function () {
this._canvas.drawImage(img, 300, 300);// this is line 14
}
The problem that I guess here, is when the resources be available?, but there is a way to confirm that the resources are available, just check 'complete' attribute of the image object.
if (img.complete == true){
// is available.
} else {
// wait until is ready.
}
Also, you can make a merge method with onload event and a delay method that checking both stuff.
var img = new Image();
//first attach handler
img.onload = function(e){
if (e.target.complete == true) {
yourHandler(e);
} else {
var maxTimes = 10;
var countTimes = 0;
function retryLoadImage() {
setTimeout(function () {
if (countTimes > maxTimes) {
// -- cannot load image.
return;
} else {
if (e.target.complete == true) {
yourHandler(e);
} else {
retryLoadImage();
}
}
countTimes++;
}, 50);
};
}
};
img.src = yourSource;
This is working for me!!! on IE and FF.

Categories