18

I have a webpage where I want the user to see a new image when they put thier mouse over a certain part of the image. I used an image map.

<img src="pic.jpg" usemap="#picmap" />
<map id="picmap" name="picmap"><area shape="rect" coords ="10,20,30,40"
onMouseOver="mouse_on_write('mouse is on spot')"
onMouseOut="mouse_off('mouse is off spot')"
href="http://www....html" target="_blank" />
</map>
<p id="desc"></p>

Where in the header I defined these functions:

 <script type="text/javascript">
 function mouse_off(txt)
    {
    document.getElementById("desc").innerHTML=txt;
    document.p1.src="pic.jpg";
    }
 function mouse_on_write(txt)
    {
    document.getElementById("desc").innerHTML=txt;
    document.p1.src="pic2.jpg";
  </script>

It works, but it is slow. When the mouse is put over the second image it takes some few seconds to appear; my temporary solution was to drastically reduce the size of the images because they were huge (at 2.5mb they switch fast now, but still not seamless). How can I make the image switching more seamless without reduction in picture quality? On second thought I realize that I could also just have both images displayed, at a small and a large scale, and on mouse over they would switch places; How would I do this? Would this reduce lag?

Alex
  • 8,521
  • 6
  • 31
  • 33
  • By the way, you're probably not going to want to inflict a 2.5 MB image on your users anyway. What are the dimensions of the space you're trying to fill? – dshaw Nov 13 '08 at 19:16

10 Answers10

39

You don't need to create any page elements, it can all be preloaded using JavaScript:

tempImg = new Image()
tempImg.src="pic2.jpg"

EDIT:

If you have a lot of images, you can use the poor-man's multi-preloader:

preloads = "red.gif,green.gif,blue.gif".split(",")
var tempImg = []

for(var x=0;x<preloads.length;x++) {
    tempImg[x] = new Image()
    tempImg[x].src = preloads[x]
}
Diodeus - James MacFarlane
  • 112,730
  • 33
  • 157
  • 176
  • 2
    This method doesn't work for me. I need to preload because I am showing a message to users right before reloading the page--an edge case, I know. However, this works if I put it in the DOM: ``. Forcing height and width to nothing keeps it from damaging the view no matter where it is, while `visibility:hidden` makes the browser load the image. – bean5 Oct 25 '13 at 19:39
  • Quick tip: Avoid at all costs to use a classic `for` loop. Use the [`forEach`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) array helper function instead. – Bruno Finger Nov 06 '17 at 11:10
15

Doing this with sprites is a good solution, because you don't have to wait to load the new image. Sprites work by combining the two images into one, and changing the background offset on mouseover.

You can even do with with CSS instead, for much faster results. There's a good tutorial on this here.

Adam Lassek
  • 35,156
  • 14
  • 91
  • 107
8

As of Javascript 1.6 this can be accomplished without any named variables:

imageList.forEach( function(path) { new Image().src=path } );
Turadg
  • 7,471
  • 2
  • 48
  • 49
3

You can also put both images in same file and offset it up and down. If it should affect element you are crossing over with mouse it could look like

a {  
  background-image: url(back.png);  
  background-repeat: no-repeat;  
  background-attachment:fixed;  
  background-position: 0 0;
}

a:hover {
  background-image: url(back.png);  
  background-repeat: no-repeat;  
  background-attachment:fixed;  
  background-position: 0 20px;  
}  

This way it can work without javascript.

If I understand your case correctly you still need javascript, but you can "preload" image this way nevertheless.

Slartibartfast
  • 8,735
  • 6
  • 41
  • 45
1

What you want todo is preload the images behind the scenes.

Then, when moused over, the browser will already have that image in its cache and will switch it over very fast.

function preloadImage(imagePath)
{
    var img = document.createElement('IMG');
    img.src = imagePath;        
}

preloadImage('BigImage');
FlySwat
  • 172,459
  • 74
  • 246
  • 311
1

Clever solution from Diodeus. However, unless there's a good reason NOT TO, you should really consider using sprites. It's a bit of work to get them setup, but the net efficiency is really worth it.

This approach is the number one rule in Steve Souder's High Performance Web Sites.

"Rule 1 - Make Fewer HTTP Requests"

Good luck and have fun. - D.

dshaw
  • 2,129
  • 2
  • 14
  • 17
1

I've noticed that 'preloading' into .src to this day doesn't work consistently across all browsers - IE7 still can't figure out how to cache / use preloaded images - you can clearly see there's a server request made every time you mouse over.

What I do is load in all images via standard HTML placement and just toggle style.display on and off.

Kon
  • 27,113
  • 11
  • 60
  • 86
0

Use display: none;, then have the Javascript change it to display: inline when you want to display it. This has the added advantage of being able to put the image exactly where you want in the page's source, rather than having to add it with Javascript later.

coppro
  • 14,338
  • 5
  • 58
  • 73
0

Here's how I do it, in pure JavaScript:

var myImgs = ['path/to/img1.jpg', 'path/to/img2.gif'];

function preload(imgs) {
    var img;
    for (var i = 0, len = imgs.length; i < len; ++i) {
        img = new Image();
        img.src = imgs[i];
    }
}

preload(myImgs);

That said, ALassek's suggestion of using CSS sprites is an excellent one, if you have scope to do it. The advantages of sprites are many: fewer HTTP requests, smaller download size (usually), works without JavaScript enabled.

Andrew Hedges
  • 21,688
  • 16
  • 67
  • 79
0

http://www.filamentgroup.com/lab/update_automatically_preload_images_from_css_with_jquery/

When we first launched the lab, we released a jQuery plugin that automatically preloads all images referenced in CSS files. We've found the script to be incredibly helpful in developing snappy applications where images are always ready when we need them. This post describes a significant update to the script which will make it even easier to integrate in existing projects.

micmcg
  • 270
  • 3
  • 8