|
定位点及显示对话框
添加以alpha透明模式叠加的定位点,并在用户点击这个定位点时弹出一个同样以alpha透明模式叠加的对话框。这里最难的部分当然是创建图像了。不过这些图片可能无法在ie6中正常显示。
现在我们需要实现定位点,坦率地说,这简直是小菜一碟。只需要在innerdiv中添加一个小地图块时,向这个图像中添加一个onclick事件句柄,该句柄能够在定位点之上的绝对位置显示对话框:
//调用标记函数
img.onclick=parameterFunction(null,\"imgOnclick\",tileName,imgLeft,imgTop);
因为javascript事件处理程序不能带参数,所以我们在此自定义了一个可以带参数的事件处理程序。(耍了一点点小聪明哦!)
将有参数的函数封装为无参数的函数
function parameterFunction(obj,strFunc) {
var args=[]; //定义args用于存储传递给事件处理程序的参数
if (!obj) obj=window; //如果是全局函数则obj=window
//得到传递给事件处理程序的参数
for (var i=2;i<arguments.length;i++) {
args.push(arguments);
}
//用无参数函数封装事件处理程序的调用
return function() {
obj[strFunc].apply(obj,args); //将参数传递给指定的事件处理函数
}
}
详细介绍见我的文章《javascript的N问》
现在我们需要实现点击事件的函数imgOnclick()。这个函数接收三个参数,tileName:小地图块的id,imgLeft:当前触发点击事件的小地图块的left属性,imgTop:当前触发点击事件的小地图块的top属性。第一个参数是为了便于向数据库查询小地图块的详细信息而定义的参数,在这个实例中没有什么用途。我们首先来清除上一次点击事件生成的定位点和对话框内容:
var pinImage = document.getElementById(\"pushPin\");
if (pinImage) {
pinImage.parentNode.removeChild(pinImage);
var dialog = document.getElementById(\"pinDialog\");
dialog.parentNode.removeChild(dialog);
return;
}
根据imgLeft和imgTop参数来生成定位点:
var innerDiv = document.getElementById(\"innerDiv\");
pinImage = document.createElement(\"img\");
pinImage.src = \"pin.png\";
pinImage.style.position = \"absolute\";
pinImage.style.left = imgLeft+100;
pinImage.style.top = imgTop+50;
pinImage.style.zIndex = 1;
pinImage.setAttribute(\"id\", \"pushPin\");
innerDiv.appendChild(pinImage);
根据imgLeft和imgTop参数来生成对话框:
var dialog = document.createElement(\"div\");
dialog.style.position = \"absolute\";
dialog.style.left = (imgLeft-90+100) + \"px\";
dialog.style.top = (imgTop-210+50) + \"px\";
dialog.style.width = \"309px\";
dialog.style.height = \"229px\";
dialog.style.backgroundImage = \"url(dialog.png)\";
dialog.style.zIndex = 2;
dialog.setAttribute(\"id\", \"pinDialog\");
dialog.innerHTML = \"<table height='80%' width='100%'>\" +
\"<tr><td align='center'><a href='searchMap.asp?id=\"+tileName+\"'>详情浏览</a></td></tr></table>\";
innerDiv.appendChild(dialog);
}
我们来回顾下imgOnclick()函数的完整代码:
function imgOnclick(tileName,imgLeft,imgTop) {
var pinImage = document.getElementById(\"pushPin\");
if (pinImage) {
pinImage.parentNode.removeChild(pinImage);
var dialog = document.getElementById(\"pinDialog\");
dialog.parentNode.removeChild(dialog);
return;
}
var innerDiv = document.getElementById(\"innerDiv\");
pinImage = document.createElement(\"img\");
pinImage.src = \"pin.png\";
pinImage.style.position = \"absolute\";
pinImage.style.left = imgLeft+100;
pinImage.style.top = imgTop+50;
pinImage.style.zIndex = 1;
pinImage.setAttribute(\"id\", \"pushPin\");
innerDiv.appendChild(pinImage);
var dialog = document.createElement(\"div\");
dialog.style.position = \"absolute\";
dialog.style.left = (imgLeft-90+100) + \"px\";
dialog.style.top = (imgTop-210+50) + \"px\";
dialog.style.width = \"309px\";
dialog.style.height = \"229px\";
dialog.style.backgroundImage = \"url(dialog.png)\";
dialog.style.zIndex = 2;
dialog.setAttribute(\"id\", \"pinDialog\");
dialog.innerHTML = \"<table height='80%' width='100%'>\" +
\"<tr><td align='center'><a href='searchMap.asp?id=\"+tileName+\"'>详情浏览</a></td></tr></table>\";
innerDiv.appendChild(dialog);
}
对于这个新功能,只有一个小问题。你是否记得在函数checkTiles()中删除图像的代码?在那个函数中显式地加入了删除innerdiv子节点中的所有图像元素的代码。当然,这也将破坏此处的定位点功能,因为他也是一个位于innerdiv中的图像子节点,所以为了定位功能,我们需要修改这个函数:
var imgs = innerDiv.getElementsByTagName(\"img\");
for (i = 0; i < imgs.length; i++) {
var id = imgs.getAttribute(\"id\");
if (!visibleTilesMap[id]) {
if (id != \"pushPin\") {
innerDiv.removeChild(imgs);
i--; // 补偿已经存在的 nodelist
}
}
}
搞定!我们已经实现了所有功能。一起来总结一下...不对,稍等一下。还有一个小小的问题。在ie6或者更低的ie版本中,我们这个地图的缩放按钮和定位点以及对话框怎么这么难看?在此,我们使用一个第三方提供的javascript库来解决这个问题。(偷懒一下,我等下还要去看古龙的《蝙蝠传奇》,所以就不自己写个类来实现了!)
首先,需要在web页面引用这个库:
<script language=\"javascript\" src=\"/js/browserdetect_lite.js\" type=\"text/javascript\">
</script>
<script language=\"javascript\"
src=\"/js/opacity.js\"
type=\"text/javascript\">
</script>
<script language=\"javascript\">
由于该javascript库需要将png图片设置为div的背景图像,因此需要把定位点图片从<img>迁移到div中。缩放按钮也需要放到div中,作为其背景图像。
<body onLoad=\"init()\">
<div id=\"outerDiv\">
<div id=\"toggleZoomDiv\" onClick=\"toggleZoom()\">
</div>
<div id=\"innerDiv\" style=\"z-index: 0\">
这里放地图
</div>
</div>
</body>
我们还可以将缩放触发器div中的样式属性放置到专门的样式表文件中:
#toggleZoomDiv {
position: absolute;
top: 10px;
left: 10px;
z-index: 1;
width: 72px;
height: 30px;
}
接着在函数init()中添加以下代码:
new OpacityObject('toggleZoomDiv','zoom').setBackground();
最后,重新规划下函数imgOnclick():
function imgOnclick(tileName,imgLeft,imgTop) {
var pinImage = document.getElementById(\"pushPin\");
if (pinImage) {
pinImage.parentNode.removeChild(pinImage);
var dialog = document.getElementById(\"pinDialog\");
dialog.parentNode.removeChild(dialog);
return;
}
var innerDiv = document.getElementById(\"innerDiv\");
pinImage = document.createElement(\"div\");
pinImage.style.position = \"absolute\";
pinImage.style.left = imgLeft+100;
pinImage.style.top = imgTop+50;
pinImage.style.width = \"37px\";
pinImage.style.height = \"34px\";
pinImage.style.zIndex = 1;
pinImage.setAttribute(\"id\", \"pushPin\");
innerDiv.appendChild(pinImage);
new OpacityObject('pushPin','pin')
.setBackground();
var dialog = document.createElement(\"div\");
dialog.style.position = \"absolute\";
dialog.style.left = (imgLeft-90+100) + \"px\";
dialog.style.top = (imgTop-210+50) + \"px\";
dialog.style.width = \"309px\";
dialog.style.height = \"229px\";
//dialog.style.backgroundImage = \"url(dialog.png)\";
dialog.style.zIndex = 2;
dialog.setAttribute(\"id\", \"pinDialog\");
dialog.innerHTML = \"<table height='80%' width='100%'>\" +
\"<tr><td align='center'><a href='1.html?id=\"+tileName+\"'>详情浏览</a></td></tr></table>\";
innerDiv.appendChild(dialog);
new OpacityObject('pinDialog','dialog')
.setBackground();
}
耶!现在我们终于完成了所有的内容。
现在再来回顾下完整的代码:
<html xmlns=\"http://www.w3.org/1999/xhtml\">
<head>
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=gb2312\" />
<title>自考中国制作</title>
<style type=\"text/css\">
#outerDiv {
height:400px;
width:600px;
border:1px solid black;
position:relative;
overflow:hidden;
}
#innerDiv{
position:relative;
left:0px;
top:0px;
}
#toggleZoomDiv {
position: absolute;
top: 10px;
left: 10px;
z-index: 1;
width: 72px;
height: 30px;
}
</style>
<script language=\"javascript\" src=\"../ajaxmap/js/browserdetect_lite.js\" type=\"text/javascript\">
</script>
<script language=\"javascript\"
src=\"../ajaxmap/js/opacity.js\"
type=\"text/javascript\">
</script>
<script language=\"javascript\">
//常量
var viewportWidth=600;
var viewportHeight=400;
var tileSize=150;
//缩放比例
var zoom=0;
var zoomSizes=[[\"600px\",\"900px\"],[\"900px\",\"1500px\"]];
//用于控制移动div
var dragging=false;
var top;
var left;
var dragStartTop;
var dragStartLeft;
//初始化函数
function init() {
//让innerDiv足够大,来显示地图
setInnerDivSize(zoomSizes[zoom][0],zoomSizes[zoom][1]);
//开启鼠标监听器以完成拖曳
var outerDiv=document.getElementById(\"outerDiv\");
outerDiv.onmousedown=startMove;
outerDiv.onmousemove=processMove;
outerDiv.onmouseup=stopMove;
//在ie中支持拖曳所必须的
outerDiv.ondragStart=function() {return false;}
new OpacityObject('toggleZoomDiv','zoom')
.setBackground();
checkTiles();
}
//开始拖曳函数
function startMove(event) {
//对于ie是必须的
if (!event) event=window.event;
dragStartLeft=event.clientX;
dragStartTop=event.clientY;
var innerDiv=document.getElementById(\"innerDiv\");
innerDiv.style.cursor=\"-moz-grab\";
top=stripPx(innerDiv.style.top);
left=stripPx(innerDiv.style.left);
dragging=true;
return false;
}
//正在拖曳函数
function processMove(event) {
if (!event) event=window.event;//针对ie
var innerDiv=document.getElementById(\"innerDiv\");
//如果有拖曳行为
if (dragging) {
innerDiv.style.top=parseFloat(top)+(event.clientY-dragStartTop);
innerDiv.style.left=parseFloat(left)+(event.clientX-dragStartLeft);
}
checkTiles();
}
//检查是否已经加入的函数
function checkTiles() {
//首先检查哪些小地图块应该在innerDiv中显示
var visibleTiles=getVisibleTiles();
//在往其中添加小地图块时,首先要检查是否已经加入了
var innerDiv=document.getElementById(\"innerDiv\");
var visibleTilesMap={};
for (i=0;i<visibleTiles.length;i++) {
var tileArray=visibleTiles;
var tileName=\"x\"+tileArray[0]+\"y\"+tileArray[1]+\"z\"+zoom;
visibleTilesMap[tileName]=true;
var img=document.getElementById(tileName);
if (!img) {
img=document.createElement(\"img\");
if (zoom==0) {
img.src=\"../ajaxmap/0/\"+tileName+\".gif\";
//判断是否到了地图边缘
if (tileArray[0]>3||tileArray[1]>5) {
return false;
}
} else {
img.src=\"../ajaxmap/1/\"+tileName+\".gif\";
//判断是否到了地图边缘
if (tileArray[0]>5||tileArray[1]>9) {
return false;
}
}
img.style.position=\"absolute\";
img.style.left=(tileArray[0]*tileSize)+\"px\";
img.style.top=(tileArray[1]*tileSize)+\"px\";
img.setAttribute(\"id\",tileName);
var imgLeft=(tileArray[0]*tileSize);
var imgTop=(tileArray[1]*tileSize);
//调用标记函数
img.onclick=parameterFunction(null,\"imgOnclick\",tileName,imgLeft,imgTop);
innerDiv.appendChild(img);
}
}
//
var imgs = innerDiv.getElementsByTagName(\"img\");
for (i = 0; i < imgs.length; i++) {
var id = imgs.getAttribute(\"id\");
if (!visibleTilesMap[id]) {
if (id != \"pushPin\") {
innerDiv.removeChild(imgs);
i--; // 补偿已经存在的 nodelist
}
}
}
//
}
//计算可见小块地图函数
function getVisibleTiles() {
//计算出innerDiv相对于outerDiv的位置
var innerDiv=document.getElementById(\"innerDiv\");
var mapX=stripPx(innerDiv.style.left);
var mapY=stripPx(innerDiv.style.top);
//计算地图块的起始行和列
var startX=Math.abs(Math.floor(mapX/tileSize))-1;
var startY=Math.abs(Math.floor(mapY/tileSize))-1;
//计算出在可见范围内的行数和列数
var tilesX=Math.ceil(viewportWidth/tileSize)+1;
var tilesY=Math.ceil(viewportHeight/tileSize)+1;
//创建一个数组来存储所有需要被载入的地图块
var visibleTileArray=[];
var counter=0;
for (x=startX;x<(tilesX+startX);x++) {
for (y=startY;y<(tilesY+startY);y++) {
visibleTileArray[counter++]=[x,y];
}
}
return visibleTileArray;
}
//停止拖曳函数
function stopMove() {
var innerDiv=document.getElementById(\"innerDiv\");
innerDiv.style.cursor=\"\";
dragging=false;
}
//把字符串类型转换成数字的函数
function stripPx(value) {
if (value==\"\") return 0;
return parseFloat(value.substring(0,value.length-2));
}
//设置内层的宽高的函数
function setInnerDivSize(width,height) {
var innerDiv=document.getElementById(\"innerDiv\")
innerDiv.style.width=width
innerDiv.style.height=height
}
//缩放函数
function toggleZoom() {
zoom = (zoom == 0) ? 1 : 0;
var innerDiv = document.getElementById(\"innerDiv\");
var imgs = innerDiv.getElementsByTagName(\"img\");
while (imgs.length > 0) innerDiv.removeChild(imgs[0]);
setInnerDivSize(zoomSizes[zoom][0], zoomSizes[zoom][1]);
checkTiles();
}
//将有参数的函数封装为无参数的函数
function parameterFunction(obj,strFunc) {
var args=[]; //定义args用于存储传递给事件处理程序的参数
if (!obj) obj=window; //如果是全局函数则obj=window
//得到传递给事件处理程序的参数
for (var i=2;i<arguments.length;i++) {
args.push(arguments);
}
//用无参数函数封装事件处理程序的调用
return function() {
obj[strFunc].apply(obj,args); //将参数传递给指定的事件处理函数
}
}
//
//
function imgOnclick(tileName,imgLeft,imgTop) {
var pinImage = document.getElementById(\"pushPin\");
if (pinImage) {
pinImage.parentNode.removeChild(pinImage);
var dialog = document.getElementById(\"pinDialog\");
dialog.parentNode.removeChild(dialog);
return;
}
var innerDiv = document.getElementById(\"innerDiv\");
pinImage = document.createElement(\"div\");
pinImage.style.position = \"absolute\";
pinImage.style.left = imgLeft+100;
pinImage.style.top = imgTop+50;
pinImage.style.width = \"37px\";
pinImage.style.height = \"34px\";
pinImage.style.zIndex = 1;
pinImage.setAttribute(\"id\", \"pushPin\");
innerDiv.appendChild(pinImage);
new OpacityObject('pushPin','pin')
.setBackground();
var dialog = document.createElement(\"div\");
dialog.style.position = \"absolute\";
dialog.style.left = (imgLeft-90+100) + \"px\";
dialog.style.top = (imgTop-210+50) + \"px\";
dialog.style.width = \"309px\";
dialog.style.height = \"229px\";
//dialog.style.backgroundImage = \"url(dialog.png)\";
dialog.style.zIndex = 2;
dialog.setAttribute(\"id\", \"pinDialog\");
dialog.innerHTML = \"<table height='80%' width='100%'>\" +
\"<tr><td align='center'><a href='1.html?id=\"+tileName+\"'>详情浏览</a></td></tr></table>\";
innerDiv.appendChild(dialog);
new OpacityObject('pinDialog','dialog')
.setBackground();
}
</script>
</head>
<body onLoad=\"init()\">
<div id=\"outerDiv\">
<div id=\"toggleZoomDiv\" onClick=\"toggleZoom()\">
</div>
<div id=\"innerDiv\" style=\"z-index: 0\">
这里放地图
</div>
</div>
</body>
</html> |
|