实现分析
地图分割、拼凑(地图网站的简单实现--图片分割小工具)
(图片来自都市圈地图)
![](https://images.cnblogs.com/cnblogs_com/ghtyan/split.jpg)
地图网站主要展现的就是地图图片,当查看或拖动地图的时候,看到的是一张完整的当前视窗地图图片,但实际上是一张张小图片拼凑而成。地图是拼凑而成那就涉及到图片是如何分割,分割的方法很多,我说一下其中一种:地图本来就是一张很大的图片,把大图当作放在二维坐标系中(单位像素),大图左上角为圆点,沿着坐标线一小块一小块的切下来,这里以256像素X256像素的正方形为一小块,切下来之后按照坐标点除以小图边长命名(比如某小块是从坐标(256,512)处开始切图,则文件名为1,2.jpg),这样就可以知道小图的位置了。网站上看到多种倍数的地图,也就是把大图缩写相应的倍数再按同样的规格切小图;不同类型的图片(比如航拍图,2D图)也就同样的道理了,至于怎么存放就按自己的思路存放,怎么存就怎么取出来。
Web中地图展现
![](https://images.cnblogs.com/cnblogs_com/ghtyan/mapLays.jpg)
网页中展现地图是通过Div层实现,一个层是作为窗口,层的大小就是看到的地图大小(简称窗口层);一个层是用来拖动时随鼠标移动的层(简称移动层),前面说道大图是当作放在二维坐标系中,那么这个层就是充当这个坐标系,你需要显示哪张小图,就把小图拼在它切出来的坐标上,要知道显示哪张小图这就得通过当前定位的坐标(center)(定位的坐标就作为窗口层的中心位置)和窗口层的宽度(width)以及高度(height)计算出要拼上去的小图。
计算推理:
横向坐标范围:center.x-width/2 至 center.x+width/2
纵向坐标范围:center.y-height/2 至 center.y+height/2
小图是一块256像素的正方形,因此
小图横向下标范围:Math.floor((center.x-width/2)/256) 至 Math.floor((center.x+width/2)/256)
小图纵向下标范围:Math.floor((center.y-height/2)/256) 至 Math.floor((center.y+height/2)256)
通过以上下标范围就可以找到相应的图片,把图片显示在相应的坐标位置上,小图是拼凑得了,还要把镜头(窗口层)移动到center这个位置,窗口层是固定的不能移动,移动是相对的那就移动一下移动层吧
移动层的Left=width/2-center.x
移动层的top=height/2-center.y
这样简单的地图显示就可以实现了,看一下还有一个遮盖层,其实这层是透明的,不影响地图的显示,其作用是避免直接操作到地图图片,以及避免IE下出现图片工具条
![](https://images.cnblogs.com/cnblogs_com/ghtyan/imagetool.jpg)
还是来看看代码和效果吧
为了好测试,把代码都写在页面上了。 查看演示 (兼容IE和Firefox )
<!
DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
>
![](/Images/OutliningIndicators/None.gif)
<
html
xmlns
="http://www.w3.org/1999/xhtml"
>
<
head
runat
="server"
>
<
title
></
title
>
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
<
style
type
="text/css"
>
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
body{
}{
margin:0px;padding:0;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
.test{
}{background-color:black;}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
.test a{
}{float:left;text-decoration: underline;color: white;background-color:black;display:block;width:200px;text-align:center}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
.test a:hover{
}{float:left;text-decoration: underline;color: black;background-color:white;display:block;width:200px}
</
style
>
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
<
script
type
="text/javascript"
>
// http://ghtyan.cnblogs.com 代码供大家学习
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*============================prototype.js中的部分函数================================*/
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Object.extend = function(destination, source)
{
for (property in source) destination[property] = source[property];
return destination;
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Function.prototype.bind = function(object)
{
var __method = this;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
return function()
{
return __method.apply(object, arguments);
}
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Function.prototype.bindAsEventListener = function(object)
{
var __method = this;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
return function(event)
{
return __method.call(object, event || window.event);
}
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
function $()
{
if (arguments.length == 1) return get$(arguments[0]);
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
function get$(el)
{
if (typeof el == 'string') el = document.getElementById(el);
return el;
}
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*============================基础类================================*/
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
function CPoint(x,y)
{ //坐标点
this.x=x;
this.y=y;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
function CSize(width,height)
{ //矩形区域
this.width=width;
this.height=height;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
function CBounds(p1,p2)
{ //矩形坐标范围,参数左上点和右下点组成
this.minX=p1.x;
this.minY=p1.y;
this.maxX=p2.x;
this.maxY=p2.y;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
this.getSize=function()
{
return new CSize(this.maxX-this.minX,this.maxY-this.minY);
}
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
window.CEvent=
{ //自定义事件处理
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
addListener:function(obj,target,act)
{
if(obj.attachEvent) obj.attachEvent("on"+target,act);
if(obj.addEventListener) obj.addEventListener(target,act,false);
},
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
removeListener:function(obj,target,act)
{
if(obj.detachEvent) obj.detachEvent("on"+target,act);
if(obj.removeEventListener) obj.removeEventListener(target,act,false);
}
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*============================地图类================================*/
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
function CMap(div)
{
this.holder=div; //地图的载体,即窗口层
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
this.config=
{
imgsize:256 //小图边长
};
this._center; //实时中心点
this.mvl; //用于移动的层,即移动层
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
this.mouseopt=
{ //鼠标在地图上操作选项
down:false, //是否按下
move:false, //是否按下并移动过
dx:0,dy:0, //按下时移动层的left和top
ex:0,ey:0 //按下时的事件坐标
};
this.mapimage=new Array();//当前显示的地图集合
this.cacheimage=new Array();//图片对象缓存,避免重复创建和删除IMG对象
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
CMap.prototype =
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
_getimage:function()
{//获取一个IMG对象
var img =this.cacheimage.shift();
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if(img==null)
{img=document.createElement("IMG");}
return img;
},
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
_loadmap:function()
{//加载地图
var bounds=this.getBounds();
var x1=Math.floor(bounds.minX/this.config.imgsize);
var x2=Math.ceil(bounds.maxX/this.config.imgsize);
var y1=Math.floor(bounds.minY/this.config.imgsize);
var y2=Math.ceil(bounds.maxY/this.config.imgsize);
this.mvl.style.left=-bounds.minX+"px";
this.mvl.style.top=-bounds.minY+"px";
for(var y=y1;y<y2;y++)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
for(var x=x1;x<x2;x++)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
var img = this._getimage();
this.mapimage.push(img);
img.style.position="absolute";
img.style.backgroundColor="#AEAEAE";
img.style.left=x*this.config.imgsize+"px";
img.style.top=y*this.config.imgsize+"px";
img.style.width=this.config.imgsize+"px";
img.style.height=this.config.imgsize+"px";
img.alt=x+","+y;
this.mvl.appendChild(img);
}
}
},
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
_resize:function(evt)
{ //地图resize事件,内部函数
this.onresize();
this._clearmap();
this._loadmap();
},
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
_mapmousedown:function(evt)
{
//记录鼠标操作信息
this.mouseopt.down=true;
this.mouseopt.ex=evt.clientX;
this.mouseopt.ey=evt.clientY;
this.mouseopt.dx=this.mvl.offsetLeft;
this.mouseopt.dy=this.mvl.offsetTop;
//为了使鼠标移动到浏览器外部,事件依然有效,IE & firefox
if(this.mvl.setCapture)
this.mvl.setCapture();
else if(window.captureEvents)
window.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP);
},
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
_mapmove:function(evt)
{
if(this.mouseopt.down==true)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//拖动时记录鼠标拖动过以及设定移动层的位置
this.mouseopt.move=true;
this.mvl.style.left=this.mouseopt.dx+(evt.clientX-this.mouseopt.ex)+"px";
this.mvl.style.top=this.mouseopt.dy+(evt.clientY-this.mouseopt.ey)+"px";
}
},
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
_mapmouseup:function(evt)
{
//取消事件捕捉
if(this.mvl.releaseCapture)
this.mvl.releaseCapture();
else if(window.releaseEvents)
window.releaseEvents(Event.MOUSEMOVE|Event.MOUSEUP);
if(this.mouseopt.down==true&&this.mouseopt.move==true)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//重新设定实时中心位置
this._clearmap();
this._center.x=this.holder.offsetWidth/2-this.mvl.offsetLeft;
this._center.y=this.holder.offsetHeight/2-this.mvl.offsetTop;
this._loadmap();
}
this.mouseopt.down=false;
this.mouseopt.move=false;
},
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
_clearmap:function()
{//清除当前地图图片,放入图片缓存
var tm;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
while((tm=this.mapimage.pop())!=null)
{
this.mvl.removeChild(tm);
this.cacheimage.push(tm);
}
}
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
CMap.prototype.init=function()
{
//创建移动层
this.holder.style.overflow="hidden";
this.mvl=document.createElement("DIV");
this.mvl.style.cssText="position:absolute;left:0;top:0;z-index:1";
this.holder.appendChild(this.mvl);
//创建遮盖层
this.cover=document.createElement("DIV");
this.cover.innerHTML=" ";
this.cover.style.cssText="position:relative;left:0;top:0;z-index:2;width:2000px;height:2000px;background-color:gray;filter:alpha(opacity=0);opacity:0;";
this.holder.appendChild(this.cover);
this._loadmap();
//事件绑定
CEvent.addListener(window,"resize",this._resize.bindAsEventListener(this));
CEvent.addListener(this.holder,"mousedown",this._mapmousedown.bindAsEventListener(this));
CEvent.addListener(this.holder,"mousemove",this._mapmove.bindAsEventListener(this));
CEvent.addListener(this.holder,"mouseup",this._mapmouseup.bindAsEventListener(this));
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
CMap.prototype.reload=function()
{ //外部强制重新加载地图
this._loadmap();
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
CMap.prototype.onresize=function(evt)
{ //地图resize事件,供外部定义函数
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
CMap.prototype.setCenter=function(p)
{
this._center = p;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
CMap.prototype.getCenter=function()
{
return this._center;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
CMap.prototype.getBounds=function()
{ //获取地图范围
var p1= new CPoint(this._center.x-this.holder.offsetWidth/2,this._center.y-this.holder.offsetHeight/2);
var p2= new CPoint(this._center.x+this.holder.offsetWidth/2,this._center.y+this.holder.offsetHeight/2)
return new CBounds(p1,p2);
}
</
script
>
</
head
>
<
body
>
<
div
id
="d_map"
style
="width:100%; background-color:gray; position:relative;overflow:hidden;"
>
</
div
>
</
body
>
</
html
>
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
<
script
type
="text/javascript"
>
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
function fit()
{
document.getElementById("d_map").style.height = document.documentElement.clientHeight+"px";
}
fit();
var map = new CMap(document.getElementById("d_map"));
map.setCenter(new CPoint(1024,2048));
map.init();
map.onresize=fit;
</
script
>
暂时先写到这里了,有时间再继续下去~~~