I want my HTML page to load like normal, but I want one section of the page to only completely load after it has retrieved all images (static and rollovers) of that section.
I have this map I created using an image map and poly shapes. When a user rolls over a certain state, an entirely new map is loaded but it creates the appearance that only that section of that map is reloaded. I have not seen this done before because changing images or colors on an image map is not possible, so I had to do it this way.
Here is the link to the page: http://www.imaspy.com/unitedStatesMap.html
As you can see it takes a while for the rollover image to load over each state... but once they are all loaded the map works perfectly. I want all the images loads before the map appears. How can I do this with JavaScript?
Thanks!
Like others have already pointed out, the usual solution is to preload the mouseOver images. This is pretty basic, RobG's answer should work fine.
However, since you have an image of the entire map for the mouseOver state of each state, that's not very friendly for your visitor's bandwidth. At 222 KB each, that amounts to (50 × 222) / 1024 ≈
10.8 MB just to load the site. I would advise you to find another solution.
Update: I thought of a mistake in the solution I proposed. For a solution and the details, see the end of the answer.
If you want to stick with you current solution as much as possible, here's what I would do:
- Keep the base image and image map in place.
- Create separate images for the mouseOver states, but cropped to just the states themselves (not the entire map).
- Find the
top
andleft
coordinates for each mouseOver image (relative to the#mapContent
div) and save these in a sort of named collection (which, in JavaScript, is just a plain object).
That object (or named collection) might look something like this:
var states = {
'newMexico': {
top: 400,
left: 300
},
'arizona': {
top: 350,
left: 250
},
};
Your preloader could look like this:
function preloadStates() {
var state, img;
for (state in states) {
img = new Image();
img.src = '/image/' + state + '.png';
states[state].img = $(img).css({
position: 'absolute',
top: states[state].top,
left: states[state].left
});
}
}
Because for .. in
enumerates over the keys in an object, state
is the name of the key (and thus the name of the state). We save a new <img />
object (wrapped in a jQuery object) into the state
collection (so we have access to it later) and we apply the top
and left
positions to it.
Now, to show those preloaded images to the user on mouseOver:
var currentState = null;
var currentImage = null;
$("#imagemap area").hover(
function () {
var image;
var state;
currentState = $(this).attr("id");
// Retrieve and show the preloaded Image:
currentImage = states[currentState].img; // <-- wrapped in jQuery-object
currentImage.appendTo('#mapContent');
},
function () {
if (currentImage !== null) {
currentImage.remove();
currentImage = null;
}
}
);
This just appends the preloaded image to the #mapContent
div. Don't forget to set #mapContent
's position
to relative
, or the position of the image will be relative to the document, not to #mapContent
.
I just thought of a glaring mistake in my proposed solution:
Since the hover images will cover the original image, the mouseOut
event would fire as soon as the hover image is shown. Listening to the mouseOut
event on the hover image instead of on the original image would circumvent this, but would result in a rectangular hit area.
Fortunately, there's a simple solution: add a transparent image on top of the original image (and the hover images) and apply the imagemap
to that, instead.
Here is a proof on concept: http://jsfiddle.net/PPvG/t8prx/
A few pointers:
Once again, make sure
#mapContent
is positioned (either relatively or absolutely).Position the transparent image absolutely at
top:0
andleft:0
and make it exactly as high and wide as the original image.Make sure the transparent image has a z-index of at least 1 (and higher than the hover images):
#overlay { z-index: 1; position: absolute; top: 0; left: 0; }
Make the overlay transparent, either by making it a 1px transparent gif or by giving it
opacity: 0
. The former is more cross-browser safe.
My apologies for the oversight. :-)