openlayers 加载瓦片详解一:加载瓦片的算法类(转自studypower的专栏)

431 查看

图片描述

我们在客户端看到的瓦片其实是一个图片列表 也就是上面的grid 类 ,每张图片都是通过http从后来请求过来的图片也就是方法getURL(bound),
每张图片都有自己的url 也就是他的请求地址,而且grid的列表的每个单元格都有边框也就是bound,那要获取每个单元格中正确的图片都是通过bound来计算而获取到相应的图片,如想要加载自己瓦片就需要重写grid中的getURL(bound)方法,这也就是最下排6个不同类型的瓦片根据自己的瓦片特点及地图服务的特点编写的类,如果你有自己的瓦片却跟上面的几种都不相同也不相似,那你可以选择重写grid类,如果你的瓦片操作跟下面的6中服务相同或者类似,那可以根据自己工作考虑重写那面6个类中的其中某一个中的getURL(bound)的方法。在计算的过程中能涉及到多个参数将在下篇来详细介绍,在这给几个重写getURL(bound)的例子, 第一个例子是网上的不过在工作中验证过,绝对可用,写的还不错给大家个参考。


1、重写grid类中的getURL(bound)方法加载本地图片(天地图)

OpenLayers.Layer.TiandituLayer = OpenLayers.Class(OpenLayers.Layer.Grid,  
        {  

            TileType : null,  
            mirrorUrls : null,  
            topLevel : null,  
            bottomLevel : null,  
            topLevelIndex : 0,  
            bottomLevelIndex : 20,  
            topTileFromX : -180,  
            topTileFromY : 90,  
            topTileToX : 180,  
            topTileToY : -90,  
            isBaseLayer : true,  
            initialize : function(name, url, options) {  

                options.topLevel = options.topLevel ? options.topLevel  
                        : this.topLevelIndex;  
                options.bottomLevel = options.bottomLevel ? options.bottomLevel  
                        : this.bottomLevelIndex;  
                options.maxResolution = this  
                        .getResolutionForLevel(options.topLevel);  
                options.minResolution = this  
                        .getResolutionForLevel(options.bottomLevel);  
                var newArguments = [ name, url, {}, options ];  
                OpenLayers.Layer.Grid.prototype.initialize.apply(this,  
                        newArguments);  
            },  

            clone : function(obj) {  

                if (obj == null) {  
                    obj = new OpenLayers.Layer.TDTLayer(this.name, this.url,  
                            this.options);  
                }  

                obj = OpenLayers.Layer.Grid.prototype.clone  
                        .apply(this, [ obj ]);  

                return obj;  
            },  

            getURL : function(bounds) {  
                var level = this.getLevelForResolution(this.map.getResolution());  
                var coef = 360 / Math.pow(2, level);  
                var Row = this.topTileFromX < this.topTileToX ? Math.round((bounds.left - this.topTileFromX) / coef) : Math.round((this.topTileFromX - bounds.right) / coef);  
                var Col = this.topTileFromY < this.topTileToY ? Math.round((bounds.bottom - this.topTileFromY) / coef): Math.round((this.topTileFromY - bounds.top) / coef);  

                var type = this.TileType;  
                if (type == "EMap") {  
                    if (level >= 2 && level <= 10) {  
                        type = "A0512_EMap";  
                    } else if (level == 11 || level == 12) {  
                        type = "B0627_EMap1112";  
                    } else if (level >= 13 && level <= 18) {  
                        type = "siwei0608";  
                    }  
                }else if(type=="RMap"){  
                    if (level >= 2 && level <= 7) {  
                        type = "sbsm0210";  
                    } else if (level >= 8 && level <= 10) {  
                        type = "sbsm0210";  
                    } else if (level >= 11 && level <= 14) {  
                        type = "e11";  
                    }else if (level >= 15 && level <= 18) {  
                        type = "sbsm1518";  
                    }  
                }  

                var url = this.url;  

                if (this.mirrorUrls != null) {  
                    url = this.selectUrl(Row, this.mirrorUrls);  
                }  

                return this.getFullRequestString({  
                    T : type,  
                    X : Row,  
                    Y : Col,  
                    L : level  
                }, url);  
            },  
            selectUrl : function(a, b) {  
                return b[a % b.length]  
            },  
            getLevelForResolution : function(res) {  
                var ratio = this.getMaxResolution() / res;  
                if (ratio < 1)  
                    return 0;  
                for ( var level = 0; ratio / 2 >= 1;) {  
                    level++;  
                    ratio /= 2;  
                }  
                return level;  
            },  
            getResolutionForLevel : function(level) {  
                return 360 / 256 / Math.pow(2, level);  
            },  
            getMaxResolution : function() {  
                return this.getResolutionForLevel(this.topLevelIndex)  
            },  
            getMinResolution : function() {  
                return this.getResolutionForLevel(this.bottomLevelIndex)  
            },  
            addTile : function(bounds, position) {  
                var url = this.getURL(bounds);  
                return new OpenLayers.Tile.Image(this, position, bounds, url,  
                        this.tileSize);  
            },  

            CLASS_NAME : "OpenLayers.Layer.TiandituLayer"  
        });  

测试页面

view plain copy print?
<!DOCTYPE html>  
<html>  
  <head>  
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">  
    <meta name="apple-mobile-web-app-capable" content="yes">  
    <title>OpenLayers Tiled Map Service Example</title>  
    <link rel="stylesheet" href="../theme/default/style.css" type="text/css">  
    <link rel="stylesheet" href="style.css" type="text/css">  
   <script src="../lib/OpenLayers.js"></script>  
    <script type="text/javascript">  

        var map, layer;  

        function init(){  
            var extent = new OpenLayers.Bounds(-180.0, -90.0, 180.0, 90.0);  
            var tempScales = [295497593.05875003,147748796.52937502,73874398.264687508,36937199.132343754,18468599.566171877];  
            var mapOptions = {  
                maxExtent: extent  
            };  
            var options= {  
                mapType:"EMap",  
                topLevel: 3,   
                bottomLevel: 20  

            };  
            map = new OpenLayers.Map("map",mapOptions);  

            layer = new OpenLayers.Layer.TiandituLayer("qincy", "http://tile0.tianditu.com/DataServer",options);  
            map.addLayer(layer);  
            map.addControls([new OpenLayers.Control.MousePosition()]);  

            map.setCenter(new OpenLayers.LonLat(106,39), 3);  

        }  
    </script>  
  </head>  
  <body onload="init()">  
    <div id="map" style="width:1000px;height:500px"></div>  
  </body>  
</html>  

2、重写TileCache类加载本地图片。
/**

  • 对自定义规则切割的图片进行拼装的类
    */
SimpleTileCache=OpenLayers.Class(OpenLayers.Layer.TileCache,{  
    initialize:function(name,url,options){  
        var tempoptions = OpenLayers.Util.extend(  
{'format': 'image/png',isBaseLayer:true},options);                    
        OpenLayers.Layer.TileCache.prototype.initialize.apply(this,[name, url, {}, tempoptions]);  
        this.extension = this.format.split('/')[1].toLowerCase();  
        this.extension = (this.extension == 'jpg') ? 'jpeg' : this.extension;  
        this.transitionEffect="resize";  
        this.buffer=2;        
    },  
    /**  
     *   按地图引擎切图规则实现的拼接方式  
     */  
    getURL: function(bounds) {            
        var res   = this.map.getResolution();                     
        var bbox  = this.map.getMaxExtent();  
        var size  = this.tileSize;  
        //计算列号                
        var tileX = Math.round((bounds.left - bbox.left) / (res * size.w));  
           //计算行号  
        var tileY = Math.round((bbox.top-bounds.top) / (res * size.h));   
        //当前的等级           
        var tileZ = this.map.zoom;                                                        
        if(tileX<0) tileX=tileX+Math.round(bbox.getWidth()/bounds.getWidth());         
        if(tileY<0)  tileY=tileY+Math.round(bbox.getHeight()/bounds.getHeight());                      
        return  this.getTilePic(tileX,tileY,tileZ);  
    },  
    getTilePic: function(tileX,tileY,tileZ){  
        var dir = '';  
        if(tileZ > 6) {  
            var delta       = Math.pow(2,tileZ-5);        
            var rowDir   = 'R'+ Math.floor(tileY /delta);  
            var colDir   = 'C'+Math.floor(tileX /delta);  
            dir      = tileZ  + "/" + rowDir + "/" + colDir + "/";  
        } else {  
            dir= tileZ + '/';  
        }                     
        var tileNo  = tileZ + "-" + tileX + "-" + tileY;  
        var sUrl = this.url + dir + tileNo + '.png';  
        return sUrl;  
    },  
    clone: function (obj) {   
        if (obj == null) {  
        obj = new SimpleTileCache(this.name,this.url,this.options);  
        }  
        obj = OpenLayers.Layer.TileCache.prototype.clone.apply(this, [obj]);  
        return obj;  
    },  
    CLASS_NAME: "SimpleTileCache"  
});  

3、直接修改TileCache类中的getURL方法

修改后 的 TileCache.js

OpenLayers.Layer.TileCache = OpenLayers.Class(OpenLayers.Layer.Grid, {  

    isBaseLayer: true,  

    format: 'image/png',  

    serverResolutions: null,  

    initialize: function(name, url, layername, options) {  
        this.layername = layername;  
        OpenLayers.Layer.Grid.prototype.initialize.apply(this,  
                                                         [name, url, {}, options]);  
        this.extension = this.format.split('/')[1].toLowerCase();  
        this.extension = (this.extension == 'jpg') ? 'jpeg' : this.extension;  
    },      

    clone: function (obj) {  

        if (obj == null) {  
            obj = new OpenLayers.Layer.TileCache(this.name,  
                                                 this.url,  
                                                 this.layername,  
                                                 this.getOptions());  
        }  

        //get all additions from superclasses  
        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);  

        // copy/set any non-init, non-simple values here  

        return obj;  
    },      

     getURL: function(bounds) {  
        var res = this.map.getResolution();  
        var x = Math.round ((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));  
        var y = Math.round ((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));  
        var z = this.map.getZoom();  
        var path =z+9+ "/" + x + "/" + y + "." + this.type;  
        var url = this.url;  
        if (url instanceof Array) {  
            url = this.selectUrl(path, url);  
        }  
        //我用resin 发布的地图瓦片的位置  
        url="http://192.168.0.90:88/roadmap2/"+path;  
        return url  
    },  

    /*getURL: function(bounds) {  
        var res = this.getServerResolution();  
        var bbox = this.maxExtent;  
        var size = this.tileSize;  
        var tileX = Math.round((bounds.left - bbox.left) / (res * size.w));  
        var tileY = Math.round((bounds.bottom - bbox.bottom) / (res * size.h));  
        var tileZ = this.serverResolutions != null ?  
            OpenLayers.Util.indexOf(this.serverResolutions, res) :  
            this.map.getZoom();  

        var components = [  
            this.layername,  
            OpenLayers.Number.zeroPad(tileZ, 2),  
            OpenLayers.Number.zeroPad(parseInt(tileX / 1000000), 3),  
            OpenLayers.Number.zeroPad((parseInt(tileX / 1000) % 1000), 3),  
            OpenLayers.Number.zeroPad((parseInt(tileX) % 1000), 3),  
            OpenLayers.Number.zeroPad(parseInt(tileY / 1000000), 3),  
            OpenLayers.Number.zeroPad((parseInt(tileY / 1000) % 1000), 3),  
            OpenLayers.Number.zeroPad((parseInt(tileY) % 1000), 3) + '.' + this.extension  
        ];  
        var path = components.join('/');   
        var url = this.url;  
        if (OpenLayers.Util.isArray(url)) {  
            url = this.selectUrl(path, url);  
        }  
        url = (url.charAt(url.length - 1) == '/') ? url : url + '/'; //url+path  
        //alert(url+path);  
        return "http://192.168.0.90:88/roadmap/1/0/0.png"  
    },*/  

    CLASS_NAME: "OpenLayers.Layer.TileCache"  
});  

测试页面

<!DOCTYPE html>  
<html>  
  <head>  
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">  
    <meta name="apple-mobile-web-app-capable" content="yes">  
    <title>OpenLayers TileCache Example</title>  
     <link rel="stylesheet" href="../theme/default/style.css" type="text/css">  
        <link rel="stylesheet" href="style.css" type="text/css">  
        <script src="../lib/OpenLayers.js"></script>  
        <script src="../lib/Firebug/firebug.js"></script>  
    <script type="text/javascript">  
    //alert("adsf");  
       var proj='EPSG:900913'; //900913  
        var map, layer;  
        var proj2 = new OpenLayers.Projection("EPSG:4326");  
        var agsTileOrigin = new OpenLayers.LonLat(-180,85);  
        agsTileOrigin.transform(proj2, new OpenLayers.Projection("EPSG:900913"));  
        //alert(agsTileOrigin.);  
        var mapExtent = new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34);  
        function init(){  

        //添加编辑图层 图层名称为editLayer  
            var EditLayer=new OpenLayers.Layer.Vector("EidtLayer");  
        //添加地图  
            map = new OpenLayers.Map( 'map', {  
                numZoomLevels:3,                             //缩放级别  
                resolutions:[305.7481,152.8741,76.437],      //分别率  单位是米  
                controls:[                          
                        new OpenLayers.Control.EditingToolbar(EditLayer), //添加编辑控件   
                        new OpenLayers.Control.Navigation(),  
                        new OpenLayers.Control.PanZoomBar(),  
                        new OpenLayers.Control.LayerSwitcher({'ascending':false}),  
                        new OpenLayers.Control.Permalink(),  
                        new OpenLayers.Control.ScaleLine(),  
                        new OpenLayers.Control.Permalink('permalink'),  
                        new OpenLayers.Control.MousePosition(),  
                        new OpenLayers.Control.OverviewMap(),  
                        new OpenLayers.Control.KeyboardDefaults()  
                        ]  
            });  
            layer = new OpenLayers.Layer.TileCache("TileCache Layer",  
                "http://c0.tilecache.osgeo.org/wms-c/cache/",  
                "basic",  
                {  
                 serverResolutions:[305.7481,152.8741,76.437],  
                                        projection:proj,  
                                        type:'png'  
                }  
            );  

            map.addLayers([layer, EditLayer]);  
            var  lob_ll=new OpenLayers.LonLat(121.34457, 31.329235);  
            map.setCenter(lob_ll.transform(proj2, new OpenLayers.Projection("EPSG:900913")), 0);  
        }  
    </script>  
    <style type="text/css">  
    html,body{width:100%;height:100%;margin:0;}  
    </style>  
  </head>  
  <body onload="init()">  
    <div id="map"  class="smallmap"  style="width:100%; height:100%; backround-color:Red;"></div>  
  </body>  
</html>