在本文中,将探讨如何利用jQueryUI和ImageMapster创建一个可拖拽的图像映射(imagemap)。这是一个有趣且具有广泛应用潜力的问题。在页面底部,提供了一个使用Marvin the Martian的简单示例,它能够正常工作,将在介绍如何实现之前解释其工作原理。
使用jQueryUI的draggable
方法,可以轻松创建可拖拽的对象。但是,由于z-index
的问题,事情变得有些棘手。当拖拽某个对象时,它需要在页面上拥有最高的z-index
,否则在拖拽过程中它会消失在其他元素后面。但同时,图像映射(imagemap)只有在拥有最高z-index
时才会激活。这似乎是一个悖论!
幸运的是,使用ImageMapster时,已经设置好了可以让拖拽元素位于顶部,同时图像映射仍然保持活跃。这是ImageMapster工作方式的本质:在绑定图像时,ImageMapster会创建图像的副本用作背景,然后使用CSS将原始图像设置为不可见(opacity:0
)。所需要做的就是确保拖拽元素的z-index
位于这两个元素之间。对ImageMapster的元素方案有一点了解就足够了:
最顶层,即HTML图像映射本身,并不是一个需要显式设置z-index
的层。然而,它确实像一个层,因为鼠标事件会在这些区域上覆盖图像本身的事件。但基本上,原始图像是最顶层的元素。
最后,所有这些内容都被包裹在一个div
中。了解这一点很有用,因为它意味着可以使用jQuery的siblings
方法轻松更改除了原始图像之外所有重要元素的z-index
。
以下是使对象在活动图像映射上可拖拽所需的基本逻辑:
var img = $('#my-image-map'), item = $('#draggable-object');
img.mapster();
...
// 在使用imageMapster绑定后,将图像的兄弟元素的z-index设置为零(最低)。
// 创建的图像副本以及渲染高亮效果的画布都是原始图像的兄弟元素。
// 在绑定ImageMapster之后。
// 重要:这必须在mapster完成绑定后执行 - 参见下面的实际代码,了解如何使用"onConfigured"来实现这一点
img.siblings().css('z-index', 0);
// 将图像本身设置为更高的值。
img.css('z-index', 10);
// 拖拽元素应该在可见的背景和效果图像(现在都设置为0)以及原始图像+图像映射(现在设置为10)之间拥有一个z-index。
item.css('z-index', 5);
这几乎就是需要做的一切。当把火星人(martian)放到某个地方时会发生什么?它现在有一个比原始图像更低的z-index。尽管图像映射是不可见的,火星人是可见的,但不能再抓住火星人,因为一旦放下它,它旧的z-index就会生效。
为了解决这个问题,需要一点更多的技巧。当有人第一次抓住可拖拽的元素时,将其z-index更改为两个图像层之间的值。但是,当他们放下它时,将其更改为比原始图像更高的值,这样它就会位于顶部,并且可以再次被拾起。
以下是实际示例,所有代码如下(或者可以使用浏览器查看)。将火星人拖放到火星上以"获胜"。任何其他行星都会给一个负面的回应,如果把他放在太空中,什么也不会发生。也在jsfiddle.net上设置了它。享受吧!
注意:这最初是作为博客文章出现的,需要JavaScript包含才能使演示工作。请去那里尝试演示或使用上面的jsfiddle链接 - 它在CodeProject上无法工作。
帮助回家!
var img = $('#planets'), martian=$('#martian');
img.mapster({
mapKey: 'alt',
fillOpacity: 0.8,
fillColor: 'ff0000',
stroke: true,
strokeWeight: 2,
strokeColor: '00ff00',
onConfigured: function() {
// 这将在ImageMapster完成设置后调用
img.siblings().css('z-index',0);
img.css('z-index',10);
}
});
martian.css('z-index',5)
.draggable({
drag: function() {
$(this).css('z-index', 5)
}
});
img.droppable({
drop: function(e,ui) {
// 将z-index设置为最高,以便可以再次拖拽
$(ui.draggable).css('z-index',20);
// 返回当前高亮项目的mapKey值
var landing=img.mapster('highlight');
if (landing=='Mars') {
alert("Thanks for bringing me home!!!");
martian.draggable('disable').hide('slow');
} else if (landing) {
alert("I don't live on " + landing);
}
}
});