正如其他人已经指出的那样,通常的解决方案是预加载 mouseOver 图像。这是非常基本的,RobG's answer 应该可以正常工作。
但是,由于您有 每个 状态的 mouseOver 状态的 整个 地图的图像,这对访问者的带宽不是很友好。每个 222 KB,这相当于 (50 × 222) / 1024 ≈ 10.8 MB 只是为了加载网站。我会建议您找到其他解决方案。
更新:我想到了我提出的解决方案中的一个错误。解决方案及详情见答案末尾。
如果您想尽可能坚持当前的解决方案,我会这样做:
- 保留基本图像和图像映射。
- 为 mouseOver 状态创建单独的图像,但仅裁剪为状态本身(而不是整个地图)。
- 找到每个 mouseOver 图像的
top 和 left 坐标(相对于 #mapContent div)并将它们保存在一种命名集合中(在 JavaScript 中,这只是一个普通的对象)。
那个对象(或命名的集合)可能看起来像这样:
var states = {
'newMexico': {
top: 400,
left: 300
},
'arizona': {
top: 350,
left: 250
},
};
您的预加载器可能如下所示:
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
});
}
}
因为for .. in 枚举对象中的键,所以state 是键的名称(因此也是状态的名称)。我们将一个新的<img /> 对象(包装在一个jQuery 对象中)保存到state 集合中(这样我们以后可以访问它),然后我们将top 和left 位置应用到它。
现在,在 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;
}
}
);
这只是将预加载的图像附加到#mapContent div。不要忘记将#mapContent的position设置为relative,否则图像的位置将相对于文档,而不是#mapContent。
更新
我只是想到了我提出的解决方案中的一个明显错误:
由于悬停图像将覆盖原始图像,mouseOut 事件将在悬停图像显示后立即触发。在悬停图像而不是原始图像上监听 mouseOut 事件可以避免这种情况,但会产生一个矩形点击区域。
幸运的是,有一个简单的解决方案:在原始图像(和悬停图像)之上添加一个透明图像,然后将imagemap 应用到该图像上。
这是一个概念证明:http://jsfiddle.net/PPvG/t8prx/
几点建议:
-
再次确保#mapContent 已定位(相对或绝对)。
-
将透明图像绝对定位在top:0 和left:0 并使其与原始图像完全一样高和宽。
-
确保透明图像的 z-index 至少为 1(并且高于悬停图像):
#overlay { z-index: 1;位置:绝对;顶部:0;左:0; }
-
通过将其设为1px transparent gif 或将其设为opacity: 0,使叠加层透明。前者更安全。
对于疏忽,我深表歉意。 :-)