OpenLayers源码学习20:WMTS Posted on 2015-03-19 | In OpenLayers学习 | 公司的协议就是wmts,看完layer和瓦片的所有内容 终于能看wmts了 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326OpenLayers.Layer.WMTS = OpenLayers.Class(OpenLayers.Layer.Grid, { isBaseLayer: true, version: "1.0.0", //对应wmts里 "REST" or "KVP"两种 requestEncoding: "KVP", // url模版. {String|Array(String)}. url: null, // url里的图层 layer: null, // url里的matrixSet matrixSet: null, //url里style style: null, //url里format format: "image/jpeg", // 左上角的单位 tileOrigin: null, // tileFullExtent: null, // REST时候用的图片编码 formatSuffix: null, /** * Matrix properties: * identifier - {String} The matrix identifier (required). * scaleDenominator - {Number} The matrix scale denominator. * topLeftCorner - {<OpenLayers.LonLat>} The top left corner of the * matrix. Must be provided if different than the layer <tileOrigin>. * tileWidth - {Number} The tile width for the matrix. Must be provided * if different than the width given in the layer <tileSize>. * tileHeight - {Number} The tile height for the matrix. Must be provided * if different than the height given in the layer <tileSize>. */ matrixIds: null, // 给RESTful 请求编码用的 dimensions: null, // KVP是<requestEncoding> params: null, //zoom偏移, 每次计算都是加上这个全局偏移量 zoomOffset: 0, // 服务器支持的分辨率列表 {Array} serverResolutions: null, //图片格式列表 formatSuffixMap: { "image/png": "png", "image/png8": "png", "image/png24": "png", "image/png32": "png", "png": "png", "image/jpeg": "jpg", "image/jpg": "jpg", "jpeg": "jpg", "jpg": "jpg" }, // matrix定义里当前map的分辨率, <updateMatrixProperties>更新 matrix: null, /** * 示例 * var wmts = new OpenLayers.Layer.WMTS({ * name: "My WMTS Layer", * url: "http://example.com/wmts", * layer: "layer_id", * style: "default", * matrixSet: "matrix_id" * }); * * config必须包括: * url - {String} service的wmts地址. 存在 <url> 属性. * layer - {String} layer id. 存在 <layer> 属性. * style - {String} style id. 存在<style> 属性. * matrixSet - {String} matrix set id. 存在 <matrixSet>属性 */ initialize: function(config) { // 必选项配置 var required = { url: true, layer: true, style: true, matrixSet: true }; //检查必选项 for (var prop in required) { if (!(prop in config)) { throw new Error("Missing property '" + prop + "' in layer configuration."); } } //构造父类 config.params = OpenLayers.Util.upperCaseObject(config.params); var args = [config.name, config.url, config.params, config]; OpenLayers.Layer.Grid.prototype.initialize.apply(this, args); // 计算formatSuffix if (!this.formatSuffix) { this.formatSuffix = this.formatSuffixMap[this.format] || this.format.split("/").pop(); } // 合并matrixIds if (this.matrixIds) { var len = this.matrixIds.length; if (len && typeof this.matrixIds[0] === "string") { var ids = this.matrixIds; this.matrixIds = new Array(len); for (var i=0; i<len; ++i) { this.matrixIds[i] = {identifier: ids[i]}; } } } }, //给父类set map setMap: function() { OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments); }, // 更新矩阵属性, 移动后计算的核心方法 updateMatrixProperties: function() { //第一步 this.matrix = this.getMatrix(); //第二步 if (this.matrix) { if (this.matrix.topLeftCorner) { this.tileOrigin = this.matrix.topLeftCorner; } if (this.matrix.tileWidth && this.matrix.tileHeight) { this.tileSize = new OpenLayers.Size( this.matrix.tileWidth, this.matrix.tileHeight ); } if (!this.tileOrigin) { this.tileOrigin = new OpenLayers.LonLat( this.maxExtent.left, this.maxExtent.top ); } if (!this.tileFullExtent) { this.tileFullExtent = this.maxExtent; } } }, //移动 moveTo:function(bounds, zoomChanged, dragging) { if (zoomChanged || !this.matrix) { this.updateMatrixProperties(); } //更新矩阵后, 调用移动 return OpenLayers.Layer.Grid.prototype.moveTo.apply(this, arguments); }, //克隆 clone: function(obj) { if (obj == null) { obj = new OpenLayers.Layer.WMTS(this.options); } //拷贝父类属性 obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]); return obj; }, getIdentifier: function() { return this.getServerZoom(); }, // 计算矩阵, // 核心方法 拖拽地图后的第一步 getMatrix: function() { var matrix; if (!this.matrixIds || this.matrixIds.length === 0) { matrix = {identifier: this.getIdentifier()};//如果没有, 实际上取的是serverZoom } else { // 优先使用 scale 去运算 if ("scaleDenominator" in this.matrixIds[0]) { // 计算wmts分母 var denom = OpenLayers.METERS_PER_INCH * OpenLayers.INCHES_PER_UNIT[this.units] * this.getServerResolution() / 0.28E-3; var diff = Number.POSITIVE_INFINITY;//规定一个最小值 var delta; for (var i=0, ii=this.matrixIds.length; i<ii; ++i) { delta = Math.abs(1 - (this.matrixIds[i].scaleDenominator / denom)); if (delta < diff) { diff = delta; matrix = this.matrixIds[i]; } } } else { // 使用zoom去取 matrix = this.matrixIds[this.getIdentifier()]; } } return matrix; }, //计算瓦片位置, 取得给定经纬度的瓦片信息 getTileInfo: function(loc) { var res = this.getServerResolution(); var fx = (loc.lon - this.tileOrigin.lon) / (res * this.tileSize.w); var fy = (this.tileOrigin.lat - loc.lat) / (res * this.tileSize.h);//和给定经纬度的距离 var col = Math.floor(fx); var row = Math.floor(fy);//在二维数组里的行列号 return { col: col, row: row, i: Math.floor((fx - col) * this.tileSize.w), j: Math.floor((fy - row) * this.tileSize.h) }; }, // 核心方法, 瓦片绘制接口 getURL: function(bounds) { bounds = this.adjustBounds(bounds);//调整bounds var url = ""; if (!this.tileFullExtent || this.tileFullExtent.intersectsBounds(bounds)) { var center = bounds.getCenterLonLat(); //中心点 var info = this.getTileInfo(center);//获得瓦片信息 var matrixId = this.matrix.identifier; var dimensions = this.dimensions, params; if (OpenLayers.Util.isArray(this.url)) { //url配成数组的话, 需要拆开 url = this.selectUrl([ this.version, this.style, this.matrixSet, this.matrix.identifier, info.row, info.col ].join(","), this.url); } else { //url就一个 url = this.url; } //RESTful 模式 if (this.requestEncoding.toUpperCase() === "REST") { params = this.params; if (url.indexOf("{") !== -1) { var template = url.replace(/\{/g, "${"); var context = { // 往context里复制 style: this.style, Style: this.style, TileMatrixSet: this.matrixSet, TileMatrix: this.matrix.identifier, TileRow: info.row, TileCol: info.col }; if (dimensions) { var dimension, i; for (i=dimensions.length-1; i>=0; --i) { dimension = dimensions[i]; context[dimension] = params[dimension.toUpperCase()]; } } url = OpenLayers.String.format(template, context); } else { // 拼接'version', 'layer' 和 'style' var path = this.version + "/" + this.layer + "/" + this.style + "/"; // 拼接dimensions if (dimensions) { for (var i=0; i<dimensions.length; i++) { if (params[dimensions[i]]) { path = path + params[dimensions[i]] + "/"; } } } // 拼接matrixSet和行列号 path = path + this.matrixSet + "/" + this.matrix.identifier + "/" + info.row + "/" + info.col + "." + this.formatSuffix; if (!url.match(/\/$/)) { url = url + "/";//末尾加/ } url = url + path; } } else if (this.requestEncoding.toUpperCase() === "KVP") { // KVP模式, params = { SERVICE: "WMTS", REQUEST: "GetTile", VERSION: this.version, LAYER: this.layer, STYLE: this.style, TILEMATRIXSET: this.matrixSet, TILEMATRIX: this.matrix.identifier, TILEROW: info.row, TILECOL: info.col, FORMAT: this.format }; url = OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this, [params]); } } return url; }, // 合并参数 mergeNewParams: function(newParams) { if (this.requestEncoding.toUpperCase() === "KVP") { return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply( this, [OpenLayers.Util.upperCaseObject(newParams)]//合并参数 ); } }, CLASS_NAME: "OpenLayers.Layer.WMTS"});