简体   繁体   中英

Load all my images contained in only one DIV

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 and left 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 .


Update

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 and left: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. :-)

The usual way to pre-load images is like:

var preLoadedImages;

function preloadImages() {
  var img;
  var imageSources = ['01.jpg','02.jpg'];
  var i = imageSources.length;
  preLoadedImages = [];

  while (i--) {
    img = new Image();
    img.src = imageSources[i];
    preLoadedImages[i] = img;
  }
}

Note that the array of image objects must persist at least long enough for all the images to be loaded (and cached), hence the use of a global to store them. You might be able to use a closure instead. This also give you a handy collection of the images and their src properties of use in other functions (eg swapping images).

If you want to wait for all the images to load before doing something, you can create a flag for each image, then put a load listener on each image that cancels its flag. When all the flags are cancelled, all the images are loaded.

Use the 'image' object. It would be something like this:

<script type="text/javascript">
    var mouseoverImg = new Image(120, 90);
    mouseoverImg.src = "img2.gif";
    var mousedownImg = new Image(120, 90);
    mousedownImg.src = "img3.gif";
</script>

Let us assume that 'img1.gif' is already there in the document. The img2.gif is displayed during mouseover and img3.gif is displayed on mousedown. You can use addEventListener or other means of event registration and that's it.

Ok, here is a more elaborate example, but I leave it to you to fine tune it.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"  
"http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="Content-Style-Type" content="text/css">
    <title>The 'image' Object</title>

    <style type="text/css">
    <!--

    -->
    </style>


    <script type="text/javascript">
        var mouseoverImg = new Image(120, 90);
        mouseoverImg.src = "img2.gif";
        var mousedownImg = new Image(120, 90);
        mousedownImg.src = "img3.gif";
    </script>

</head>

<body>
    <h1>The 'image' Object</h1>

    <p>
        <img id="img01" src="img1.gif" width="120" height="90"  
title="image 1" alt="Image 1" />
    </p>

    <script type="text/javascript">

        var img01 = document.getElementById("img01");
        img01.addEventListener("mouseover", rolloverImg, false);
        img01.addEventListener("mouseout", rolloverImg, false);
        img01.addEventListener("mousedown", rolloverImg, false);

        var currentImg = "img1";

        function rolloverImg(e) {
            if (e.type == "mouseover") {
                img01.src = mouseoverImg.src;
            } else if (e.type == "mouseout") {
                img01.src = "img1.gif";
            } else if (e.type == "mousedown") {
                img01.src = mousedownImg.src;
            }           
        }

    </script>

</body>
</html>

You can use some random button-like images which you can download from somewhere; make sure they are named "img1.gif", "img2.gif" and "img3.gif". This example is only a demonstration. You need to adapt it for your needs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM