WebGLLayer.js 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589
  1. /* COPYRIGHT 2012 SUPERMAP
  2. * 本程序只能在有效的授权许可下使用。
  3. * 未经许可,不得以任何手段擅自使用或传播。*/
  4. /**
  5. * Class: SuperMap.Layer.WebGLLayer
  6. * 使用webgl方式进行渲染的图层
  7. * 使用此图层依赖了部分矩阵计算,所以需要引用examples/js/glMatrix-0.9.5.min.js库
  8. * Inherits from:
  9. * - <SuperMap.Layer.Grid>
  10. */
  11. SuperMap.Layer.WebGLLayer = SuperMap.Class(SuperMap.Layer.Grid, {
  12. /**
  13. * Constant: DEFAULT_PARAMS
  14. * {Object} 设置到瓦片url请求上的参数的默认值。
  15. * transparent(图层是否透明,默认为false)
  16. * 和cacheEnabled(是否使用服务端的缓存,默认为true)
  17. */
  18. DEFAULT_PARAMS: {
  19. //maxVisibleVertex: 360000,
  20. transparent: false,
  21. cacheEnabled: true
  22. },
  23. /**
  24. * Property: prjStr
  25. * {String}
  26. * 投影键值串,在图层初始化完成时赋值。例如:prjCoordSys={"epsgCode":3857}
  27. * 内部使用,不公开
  28. */
  29. prjStr1: null,
  30. /**
  31. * Property: getmapstatusservice
  32. * {String}
  33. */
  34. getMapStatusService: null,
  35. /**
  36. * Property: viewBounds
  37. * {Object} 地图窗口显示区域的范围。
  38. */
  39. viewBounds: null,
  40. /**
  41. * Property: viewer
  42. * {Object} 用户显示视窗。
  43. */
  44. viewer: null,
  45. /**
  46. * Property: scale
  47. * {Number} 地图的显示比例尺。
  48. */
  49. scale: null,
  50. /**
  51. * Property: overlapDisplayed
  52. * {Boolean} 地图对象在同一范围内时,是否重叠显示,默认为true。
  53. */
  54. overlapDisplayed: true,
  55. /**
  56. * Property: redirect
  57. * {Boolean} 是否重定向,HTTP 传输中的一个概念。如果为 true,则将请求重定向到图片的真实地址;
  58. * 如果为 false,则响应体中是图片的字节流。默认为 false,不进行重定向。
  59. */
  60. redirect: false,
  61. /**
  62. * Property: overlapDisplayedOptions
  63. * {<SuperMap.REST.OverlapDisplayedOptions>} 避免地图对象压盖显示的过滤选项,
  64. * 当 overlapDisplayed为 false 时有效,用来增强对地图对象压盖时的处理。
  65. */
  66. overlapDisplayedOptions: null,
  67. /**
  68. * Property: useCanvas
  69. * {Boolean} 设置是否将一个图层用Canvas元素显示,默认为true,只能为true
  70. *
  71. */
  72. useCanvas: true,
  73. /**
  74. * Property: canvas
  75. * 当useCanvas为true时,此Canvas作为所有瓦片的现实容器。
  76. */
  77. canvas: null,
  78. /**
  79. * Property: canvasContext
  80. * {Canvas} WEBGL的上下文。
  81. */
  82. canvasContext: null,
  83. /**
  84. * Property: lastResolution
  85. * canvas最后一次绘制的分辨率。
  86. */
  87. lastResolution: null,
  88. /**
  89. * Property: lastCanvasPosition
  90. * canvas最后一次绘制时,距左上角的位置。
  91. */
  92. lastCanvasPosition: null,
  93. /**
  94. * Property: redrawCanvas
  95. * Indicates if the canvas element should be reset before
  96. * the next tile is drawn.
  97. * 表明canvas元素是否需要在绘制之前重置,默认为false。
  98. */
  99. redrawCanvas: false,
  100. /**
  101. * Property: format
  102. * {String} 地图服务的图片格式。
  103. * 默认值为 png ,目前支持 png、jpg、bmp、gif。
  104. */
  105. format: "png",
  106. /**
  107. * Property: dpi
  108. * {Float} 屏幕上每英寸包含像素点的个数。
  109. * 该参数结合图层比例尺可以推算出该比例尺下图层的分辨率。
  110. */
  111. dpi: null,
  112. /**
  113. * Property: isBaseLayer
  114. * {Boolean} 图层是否为底图,默认为true。
  115. */
  116. isBaseLayer: true,
  117. /**
  118. * Property: tileOriginCorner
  119. * {String} 网格的原点位置。(当<tileOrigin>属性未被设置时,此属性有效)。
  120. * 可选的值包括"tl" (左上), "tr" (右上), "bl" (左下), and "br"(右下), 默认为 "tl"。
  121. */
  122. tileOriginCorner: "tl",
  123. /**
  124. * Property: datumAxis
  125. * {Number} 地理坐标系统椭球体长半轴。用户自定义地图的Options时,若未指定该参数的值,
  126. * 则DPI默认按照WGS84参考系的椭球体长半轴6378137来计算。
  127. */
  128. datumAxis: null,
  129. /**
  130. * Property: timeoutID
  131. * {Number} 记录setTimeout的索引值。
  132. */
  133. timeoutID :null,
  134. /**
  135. * Property: memoryImg
  136. * {Object} 存放已经加载的图片作为缓存。
  137. * 在每次图层状态改变时需要重绘,就会首先读取此缓存内部是否已经存在此图片,
  138. * 如果存在直接取出进行绘制,不存在再向服务器发送请求。
  139. * 这样可以提高效率,并且在断网状态下也可以查看缓存的图片。
  140. */
  141. memoryImg: null,
  142. /**
  143. * Property: memoryKeys
  144. * {Array} 保存已经缓存图片的key值。
  145. * 每一张图片有对应一个key,如x0y1z2,
  146. * 代表缩放级别为2下的第一横排,第二竖排的图片(从左上角开始计算).
  147. */
  148. memoryKeys:[],
  149. /**
  150. * APIProperty: bufferImgCount
  151. * {Number} 用来记录内存中缓存图片的数量,默认值为 1000。
  152. * 为了减少网络访问量,在使用 Canvas 模式时,图层会将访问过的图片保存在内存中,
  153. * 如果访问的图片数量超过该属性定义的值,那么新访问的图片会替换已经缓存的图片。
  154. */
  155. bufferImgCount:1000,
  156. /**
  157. * Property: isFirstLoad
  158. * {Bool} 记录是否第一次加载,默认为true。
  159. */
  160. isFirstLoad: true,
  161. /**
  162. * Property: zoomDuration
  163. * {Number} 设置两次滚轮事件触发的间隔,如果两次滚轮触发时间差小于500ms。
  164. * 则放弃前一次滚轮事件。(设置此属性的同时设置<SuperMap.Handler.MouseWheel>的interval属性,会产生错误)
  165. */
  166. zoomDuration:500,
  167. /**
  168. * Property: isZoomming
  169. * {bool} 记录是否在缩放。
  170. */
  171. isZoomming: null,
  172. /**
  173. * Property: useHighSpeed
  174. * {bool} 记录是否采用高速读图策略。
  175. */
  176. useHighSpeed:true,
  177. /**
  178. * Property: changeDx
  179. * {Interger} 记录位置的改变量。
  180. */
  181. changeDx: null,
  182. /**
  183. * Property: changeDy
  184. * {Interger} 记录位置的改变量。
  185. */
  186. changeDy: null,
  187. /**
  188. * Property: lenColumn
  189. * {Interger} 记录当前grid的col长度。
  190. */
  191. lenColumn: null,
  192. /**
  193. * Property: lenRow
  194. * {Interger} 记录当前grid的row长度。
  195. */
  196. lenRow: null,
  197. /**
  198. * Porperty: sdcardPath
  199. * {String} 记录手机当前SDCard位置。
  200. */
  201. sdcardPath:null,
  202. /**
  203. * Porperty: storageType
  204. * {String} 离线存储类型为文件格式。
  205. */
  206. storageType:"File",
  207. /**
  208. * Porperty: transitionObj
  209. * {Object} 缩放动画对象。
  210. */
  211. transitionObj: null,
  212. /**
  213. * Property: inZoom
  214. * {Boolean} 当前地图操作是否在缩放过程中。
  215. */
  216. inZoom: false,
  217. /**
  218. * Constructor: SuperMap.Layer.WebGLLayer
  219. * 使用webgl方式进行渲染的图层
  220. *
  221. * Parameters:
  222. * name - {String} 图层名称。
  223. * url - {String} 图层的服务地址。
  224. * params - {Object} 设置到url上的可选参数。
  225. * options - {Object} 附加到图层属性上的可选项,父类与此类开放的属性。
  226. */
  227. initialize: function (name, url, params, options) {
  228. //通过浏览器获取部分信息
  229. var me = this, broz = SuperMap.Browser;
  230. //me.tileSize = new SuperMap.Size(256, 256);
  231. //判断是否为移动端,如果是,那么设置缓存图片上限为500,比电脑上少了一半(考虑到手持端内存)
  232. if(!!SuperMap.isApp)me.bufferImgCount = 500;
  233. SuperMap.Layer.Grid.prototype.initialize.apply(me, arguments);
  234. //reports the progress of a tile filter
  235. if(me.useCanvas) {
  236. //通过浏览器的判定决定是否支持Canvas绘制
  237. me.useCanvas = SuperMap.Util.supportCanvas();
  238. }
  239. //如果为android手持端,那么不能支持Canvas绘制
  240. if(broz.device === 'android') {
  241. me.useCanvas = false;
  242. }
  243. if (SuperMap.isApp) {
  244. //me.sdcardPath = "file://" + window.plugins.localstoragemanager.getsdcard().sdcard + "/";
  245. cordova.exec(function(obj){
  246. me.sdcardPath = "file://" + obj.sdcard + "/";
  247. }, function(e){}, "LocalStoragePlugin","getsdcard", []);
  248. me.useCanvas = true;
  249. }
  250. if(me.useCanvas) {
  251. me.canvas = document.createElement("canvas");
  252. me.canvas.id = "Canvas_" + me.id;
  253. me.canvas.style.position = "absolute";
  254. me.div.appendChild(me.canvas);
  255. me.canvasContext = me.canvas.getContext('experimental-webgl');
  256. me.transitionObj = new SuperMap.Animal(me);
  257. me.memoryImg = {};
  258. }
  259. //如果是Canvas策略采用高速出图 。
  260. me.useHighSpeed = me.useCanvas ? true : false;
  261. me.isFirstLoad = true;
  262. //子类的代码
  263. SuperMap.Util.applyDefaults(me.params, me.DEFAULT_PARAMS);
  264. me.events.addEventType("layerInitialized");
  265. me.events.addEventType("loadError");
  266. if (me.params.transparent) {
  267. if (me.format === "jpg") {
  268. me.format = SuperMap.Util.alphaHack() ? "gif" : "png";
  269. }
  270. if (me.format === "bmp") {
  271. me.format = SuperMap.Util.alphaHack() ? "bmp" : "png";
  272. }
  273. }
  274. if (typeof me.params.clipRegion !== "undefined") {
  275. if (me.params.clipRegion instanceof SuperMap.Geometry) {
  276. me.params.clipRegionEnabled = true;
  277. var sg = SuperMap.REST.ServerGeometry.fromGeometry(me.params.clipRegion);
  278. me.params.clipRegion = SuperMap.Util.toJSON(sg);
  279. } else {
  280. delete me.params.clipRegion;
  281. }
  282. }
  283. if (typeof me.params.layersID !== "undefined") {
  284. if (!me.params.layersID){
  285. delete me.params.layersID;
  286. }
  287. }
  288. if (me.params.redirect) {
  289. me.redirect = true;
  290. }
  291. //用户传Layer的地图单位
  292. if(me.units){
  293. me.units = me.units.toLowerCase();
  294. }
  295. if(me.dpi && me.maxExtent &&(me.resolutions || me.scales)) {
  296. //如果设置了dpi、maxExtent、resolutions或者是scales,则不需要向服务端发出请求获取图层信息
  297. }else if(!me.dpi && (!me.viewBounds || !me.viewer || !me.scale)) {
  298. //当在options中设置viewBounds 、viewer 、scale 、units 、datumAxis,则计算dpi
  299. if (!!SuperMap.isApp) {
  300. var layerContext = {
  301. tile:me
  302. };
  303. cordova.exec(function(layerContext){
  304. return function(r){
  305. layerContext.tile.getAppStatusSucceed(layerContext,r);
  306. }
  307. }(layerContext), function(e){},
  308. "LocalStoragePlugin","getconfig",
  309. [this.name,this.storageType]
  310. );
  311. } else{
  312. var strServiceUrl = me.url;
  313. if (SuperMap.Util.isArray(url)) {
  314. strServiceUrl = url[0];
  315. }
  316. var getMapStatusService = new SuperMap.REST.MapService(strServiceUrl,
  317. {eventListeners: {processCompleted: me.getStatusSucceed, scope: me,
  318. processFailed: me.getStatusFailed}, projection: me.projection});
  319. getMapStatusService.processAsync();
  320. }
  321. }
  322. if (me.projection) {
  323. if(typeof me.projection == "string") {
  324. me.projection = new SuperMap.Projection(me.projection);
  325. }
  326. var arr = me.projection.getCode().split(":");
  327. if (arr instanceof Array && arr.length == 2) {
  328. me.prjStr1 = "{\"epsgCode\":" + arr[1] + "}";
  329. }
  330. }
  331. },
  332. getAppStatusSucceed:function(layerContext,r) {
  333. var mapStatus = r.json;
  334. var me = this;
  335. if (mapStatus != "false")
  336. {
  337. mapStatus = eval('(' + mapStatus + ')');
  338. var bounds = mapStatus.bounds;
  339. bounds = new SuperMap.Bounds(bounds.left,bounds.bottom,bounds.right,bounds.top);
  340. me.maxExtent = bounds;
  341. if(mapStatus.dpi){
  342. me.dpi = mapStatus.dpi;
  343. me.options.scales = mapStatus.scales;
  344. me.units = mapStatus.unit;
  345. me.datumAxis = 6378137;
  346. }
  347. else{
  348. var viewBounds = mapStatus.viewBounds,
  349. coordUnit = mapStatus.coordUnit,
  350. viewer = mapStatus.viewer,
  351. scale = mapStatus.scale,
  352. datumAxis = mapStatus.datumAxis;
  353. //将jsonObject转化为SuperMap.Bounds,用于计算dpi。
  354. viewBounds = new SuperMap.Bounds(viewBounds.left,viewBounds.bottom,viewBounds.right,viewBounds.top);
  355. me.viewBounds = viewBounds;
  356. viewer = new SuperMap.Size(viewer.rightBottom.x, viewer.rightBottom.y);
  357. me.viewer = viewer;
  358. me.scale = scale;
  359. coordUnit = coordUnit.toLowerCase();
  360. me.units = me.units || coordUnit;
  361. me.datumAxis = datumAxis;
  362. me.dpi = SuperMap.Util.calculateDpi(viewBounds, viewer, scale, me.units, datumAxis);
  363. }
  364. me.events.triggerEvent('layerInitialized',me);
  365. }else{
  366. var strServiceUrl = me.url;
  367. if (SuperMap.Util.isArray(me.url)) {
  368. strServiceUrl = me.url[0];
  369. }
  370. var getMapStatusService = new SuperMap.REST.MapService(strServiceUrl,
  371. {eventListeners:{processCompleted: me.getStatusSucceed, scope: me,
  372. processFailed: me.getStatusFailed}, projection: me.projection});
  373. getMapStatusService.processAsync();
  374. }
  375. },
  376. /**
  377. * Method: setMapStatus
  378. * 计算Dpi,设置maxExtent。
  379. */
  380. getStatusSucceed: function(mapStatus) {
  381. var me = this;
  382. if (mapStatus.result){
  383. // 当用户未设置scales,visibleScales存在值、visibleScalesEnable为true时,使layer.scales=visibleScales。
  384. var visScales = null;
  385. var orResult = mapStatus.originResult;
  386. if(orResult){
  387. visScales = orResult.visibleScales;
  388. if(!me.scales && orResult.visibleScalesEnabled && (visScales &&visScales.length&&visScales.length>0))
  389. {
  390. this.options.scales=visScales;
  391. }
  392. }
  393. var mapStatus = mapStatus.result;
  394. var bounds = mapStatus.bounds, viewBounds = mapStatus.viewBounds,
  395. coordUnit = mapStatus.coordUnit,
  396. viewer = mapStatus.viewer,
  397. scale = mapStatus.scale,
  398. datumAxis = mapStatus.datumAxis;
  399. //将jsonObject转化为SuperMap.Bounds,用于计算dpi。
  400. viewBounds = new SuperMap.Bounds(viewBounds.left,viewBounds.bottom,viewBounds.right,viewBounds.top);
  401. me.viewBounds = viewBounds;
  402. viewer = new SuperMap.Size(viewer.rightBottom.x, viewer.rightBottom.y);
  403. me.viewer = viewer;
  404. me.scale = scale;
  405. bounds = new SuperMap.Bounds(bounds.left,bounds.bottom,bounds.right,bounds.top);
  406. me.maxExtent = bounds;
  407. coordUnit = coordUnit.toLowerCase();
  408. me.units = me.units || coordUnit;
  409. me.datumAxis = datumAxis;
  410. me.dpi = SuperMap.Util.calculateDpi(viewBounds, viewer, scale, me.units, datumAxis);
  411. if (!!SuperMap.isApp){
  412. //window.plugins.localstoragemanager.savaconfig(this.name,mapStatus);
  413. cordova.exec(function(){}, function(e){}, "LocalStoragePlugin","savaconfig", [this.name,mapStatus]);
  414. }
  415. me.events.triggerEvent('layerInitialized',me);
  416. }
  417. },
  418. /**
  419. * Method: getStatusFailed
  420. * 获取图层状态失败
  421. */
  422. getStatusFailed: function(failedMessage) {
  423. var me = this;
  424. me.events.triggerEvent('loadError',failedMessage);
  425. },
  426. /**
  427. * Method: getTileUrl
  428. * 获取瓦片的URL。
  429. *
  430. * Parameters:
  431. * xyz - {Object} 一组键值对,表示瓦片X, Y, Z方向上的索引。
  432. *
  433. * Returns
  434. * {String} 瓦片的 URL 。
  435. */
  436. getTileUrl: function (xyz) {
  437. var me = this,
  438. newParams,
  439. tileSize = me.tileSize,
  440. scale = me.scales[xyz.z];
  441. //在没有设置任何投影的情况下,比例尺可能大于1,为了提高容错能力,注释掉比例尺矫正函数。 maoshuyu
  442. //scale = SuperMap.Util.normalizeScale(scale);
  443. if(!scale)scale = this.getScaleForZoom(xyz.z);
  444. newParams = {
  445. "width" : tileSize.w,
  446. "height" : tileSize.h,
  447. "x" : xyz.x,
  448. "y" : xyz.y,
  449. "scale" : scale,
  450. //hansj,忽略后面的注释//由于服务器关于缓存有问题,所以redirect先设为false。
  451. "redirect" : me.redirect
  452. };
  453. if (SuperMap.Credential.CREDENTIAL) {
  454. newParams[SuperMap.Credential.CREDENTIAL.name] = SuperMap.Credential.CREDENTIAL.getValue();
  455. }
  456. if (!me.params.cacheEnabled) {
  457. newParams.t = new Date().getTime();
  458. }
  459. if (typeof me.params.layersID !== "undefined" && typeof newParams.layersID == "undefined") {
  460. if (me.params.layersID && me.params.layersID.length > 0){
  461. newParams.layersID = me.params.layersID;
  462. }
  463. }
  464. if (me.prjStr1) {
  465. newParams.prjCoordSys = me.prjStr1;
  466. }
  467. return me.getFullRequestString(newParams);
  468. },
  469. /**
  470. * Method: getFullRequestString
  471. * 将参数与URL合并,获取完整的请求地址。(重写基类方法)
  472. *
  473. * Parameters:
  474. * newParams - {Object}
  475. * altUrl - {String}
  476. *
  477. * Returns:
  478. * {String}
  479. */
  480. getFullRequestString:function(newParams, altUrl) {
  481. var me = this,
  482. url = altUrl || this.url,
  483. allParams, paramsString, urlParams;
  484. allParams = SuperMap.Util.extend({}, me.params),
  485. allParams = SuperMap.Util.extend(allParams, newParams);
  486. if(allParams.overlapDisplayed === false) {
  487. me.overlapDisplayedOptions = allParams.overlapDisplayedOptions;
  488. me.overlapDisplayed = allParams.overlapDisplayed;
  489. delete allParams.overlapDisplayed;
  490. delete allParams.overlapDisplayedOptions;
  491. }
  492. paramsString = SuperMap.Util.getParameterString(allParams);
  493. if (SuperMap.Util.isArray(url)) {
  494. var s = "" + newParams.x + newParams.y;
  495. url = me.selectUrl(s, url);
  496. }
  497. url = url + "/tileImage." + me.format;
  498. urlParams = SuperMap.Util.upperCaseObject(SuperMap.Util.getParameters(url));
  499. for (var key in allParams) {
  500. if(key.toUpperCase() in urlParams) {
  501. delete allParams[key];
  502. }
  503. }
  504. paramsString = SuperMap.Util.getParameterString(allParams);
  505. if( me.tileOrigin ){
  506. paramsString = paramsString + "&origin={\"x\":" + me.tileOrigin.lon + "," + "\"y\":" + me.tileOrigin.lat + "}";
  507. }
  508. if(me.overlapDisplayed === false) {
  509. me.overlapDisplayedOptions = me.overlapDisplayedOptions ? me.overlapDisplayedOptions : new SuperMap.REST.OverlapDisplayedOptions();
  510. paramsString += "&overlapDisplayed=false&overlapDisplayedOptions="+ me.overlapDisplayedOptions.toString();
  511. }
  512. return SuperMap.Util.urlAppend(url, paramsString);
  513. },
  514. /**
  515. * Method: mergeNewParams
  516. * 动态修改URL的参数。(重写基类方法)
  517. *
  518. * Parameters:
  519. * newParams - {Object}
  520. *
  521. * Returns
  522. * {Boolean} 修改是否成功。
  523. */
  524. mergeNewParams: function (newParams) {
  525. if (typeof (newParams.clipRegion) != "undefined") {
  526. if (newParams.clipRegion instanceof SuperMap.Geometry) {
  527. newParams.clipRegionEnabled = true;
  528. var sg = SuperMap.REST.ServerGeometry.fromGeometry(newParams.clipRegion);
  529. newParams.clipRegion = SuperMap.Util.toJSON(sg);
  530. } else {
  531. delete newParams.clipRegion;
  532. }
  533. }
  534. return SuperMap.Layer.HTTPRequest.prototype.mergeNewParams.apply(this, [newParams]);
  535. },
  536. /**
  537. * Method: removeMap
  538. * rewrite Grid.removeMap method to clear '_timeoutId'
  539. * Called when the layer is removed from the map.
  540. *
  541. * Parameters:
  542. * map - {<SuperMap.Map>} The map.
  543. */
  544. removeMap: function(map) {
  545. SuperMap.Layer.Grid.prototype.removeMap.apply(this, [map])
  546. this._timeoutId && window.clearTimeout(this._timeoutId);
  547. this._timeoutId = null;
  548. },
  549. /**
  550. * APIMethod: destroy
  551. * 解构Layer类,释放资源。
  552. */
  553. destroy: function () {
  554. var me = this;
  555. if(me.getMapStatusService) {
  556. me.getMapStatusService.events.listeners = null;
  557. me.getMapStatusService.destroy();
  558. }
  559. me.viewBounds = null;
  560. me.viewer = null;
  561. me.scale = null;
  562. SuperMap.Layer.Grid.prototype.destroy.apply(me, arguments);
  563. me.format = null;
  564. me.dpi = null;
  565. me.datumAxis = null;
  566. me.isBaseLayer = null;
  567. me.tileOriginCorner = null;
  568. me.tileSize = null;
  569. me.bufferContext = null;
  570. if(me.transitionObj){
  571. me.transitionObj.destroy();
  572. me.trnasitionObj = null;
  573. }
  574. if (me.useCanvas) {
  575. me.canvas = null;
  576. me.memoryImg = null;
  577. }
  578. me.DEFAULT_PARAMS = null;
  579. },
  580. /**
  581. * APIMethod: clone
  582. * 创建当前图层的副本。
  583. *
  584. * Parameters:
  585. * obj - {Object}
  586. *
  587. * Returns:
  588. * {<SuperMap.SuperMap.Layer>} 新创建的图层
  589. */
  590. clone: function (obj) {
  591. var me = this;
  592. if (obj == null) {
  593. obj = new SuperMap.Layer.WebGLLayer(
  594. me.name, me.url, me.params, me.getOptions());
  595. }
  596. obj = SuperMap.Layer.Grid.prototype.clone.apply(me, [obj]);
  597. obj._timeoutId = null;
  598. return obj;
  599. },
  600. /**
  601. * Method: moveTo
  602. * 当map移动时,出发此事件. 所有的瓦片移动操作实际是
  603. * 由map完成, moveTo's 的任务是接受一个bounds,并且确定
  604. * 此bounds下的所请求的图片是否被预加载。
  605. *
  606. * Parameters:
  607. * bounds - {<SuperMap.Bounds>}
  608. * zoomChanged - {Boolean}
  609. * dragging - {Boolean}
  610. */
  611. moveTo: function(bounds, zoomChanged, dragging) {
  612. var me = this,
  613. ratio = this.lastResolution / this.map.getResolution(),
  614. style = this.map.layerContainerDiv.style,
  615. left = parseInt(style.left),
  616. top = parseInt(style.top);
  617. this.inZoom = zoomChanged ? true: false;
  618. this.changeDx = -left;
  619. this.changeDy = -top;
  620. //如果是缩放出发的moveto,不进行fixposition。
  621. //当在缩放时进行平移,不能触发fixPosition(),因为
  622. //新图没有读出来,会出图错误。
  623. if(!zoomChanged && !me.isZoomming && me.useCanvas){
  624. this.fixPosition();
  625. }
  626. SuperMap.Layer.HTTPRequest.prototype.moveTo.apply(me, arguments);
  627. bounds = bounds || me.map.getExtent();
  628. // 当操作为移动时候,并不重绘整个canvas
  629. me.redrawCanvas = zoomChanged;
  630. me.dragging = dragging;
  631. // the new map resolution
  632. var resolution = this.map.getResolution();
  633. // 当一切缩放属性都添加完后才能进行缩放动画。
  634. if (me.useCanvas && ratio!=1) {
  635. if (!zoomChanged || dragging || (this.lastResolution === null) || (this.lastCanvasPosition === null)) {
  636. } else {
  637. var lefttop = this.getLayerPxFromLonLat(this.lastCanvasPosition);
  638. if(!this.map.isIEMultipTouch){
  639. // this.transitionObj.begin(this.canvas, lefttop);
  640. }
  641. }
  642. }
  643. if (bounds != null) {
  644. // 当grid为空,或是进行缩放必须重绘整个canvas
  645. var forceReTile = !me.grid.length || zoomChanged;
  646. // 获取所有tiles的bounds
  647. var tilesBounds = me.getTilesBounds();
  648. if (this.singleTile) {
  649. if ( forceReTile ||
  650. (!dragging && !tilesBounds.containsBounds(bounds))) {
  651. if(zoomChanged && this.transitionEffect !== 'resize') {
  652. this.removeBackBuffer();
  653. }
  654. if(!zoomChanged || this.transitionEffect === 'resize') {
  655. this.applyBackBuffer(resolution);
  656. }
  657. this.initSingleTile(bounds);
  658. }
  659. } else {
  660. if (forceReTile || !tilesBounds.containsBounds(bounds, true)) {
  661. if(this.useCanvas){
  662. //判断是否第一次加载
  663. if(this.isFirstLoad){
  664. this.redrawCanvas = true;
  665. this.inZoom = true;
  666. this.isFirstLoad = false;
  667. }
  668. }
  669. if(this.zoomDuration && me.useCanvas) {
  670. this.resetCanvas();
  671. this.isZoomming = true;
  672. window.clearTimeout(this._timeoutId);
  673. this._timeoutId = window.setTimeout(
  674. SuperMap.Function.bind(function(){
  675. this.initGriddedTiles(bounds);
  676. }, this),
  677. this.zoomDuration
  678. );
  679. } else {
  680. if(zoomChanged && this.transitionEffect === 'resize') {
  681. this.applyBackBuffer(resolution);
  682. }
  683. this.initGriddedTiles(bounds);
  684. }
  685. } else {
  686. this.scheduleMoveGriddedTiles();
  687. }
  688. }
  689. }
  690. //通过改变量计算缩放前canvas左上角的地理位置。
  691. if (me.useCanvas){
  692. //获取改变量的位置。
  693. var canvasPosition = new SuperMap.Pixel(this.changeDx, this.changeDy);
  694. //通过改变量计算canvas的地理位置。
  695. this.lastCanvasPosition = this.map.getLonLatFromLayerPx(canvasPosition);
  696. }
  697. },
  698. /**
  699. * Method: scheduleMoveGriddedTiles
  700. * 将移动tile加入计划当中去。
  701. */
  702. scheduleMoveGriddedTiles: function() {
  703. if(this.useHighSpeed){
  704. this.moveGriddedTiles();
  705. }else{
  706. this.timerId && window.clearTimeout(this.timerId);
  707. this.timerId = window.setTimeout(
  708. this._moveGriddedTiles,
  709. this.tileLoadingDelay
  710. );
  711. }
  712. },
  713. /**
  714. * Method: moveGriddedTiles
  715. */
  716. moveGriddedTiles: function() {
  717. var shifted = true;
  718. var buffer = this.buffer || 1;
  719. var tlLayer = this.grid[0][0].position;
  720. var offsetX = -this.changeDx;
  721. var offsetY = -this.changeDy;
  722. var tlViewPort = tlLayer.add(offsetX, offsetY);
  723. if (tlViewPort.x > -this.tileSize.w * (buffer - 1)) {
  724. this.shiftColumn(true);
  725. } else if (tlViewPort.x < -this.tileSize.w * buffer) {
  726. this.shiftColumn(false);
  727. } else if (tlViewPort.y > -this.tileSize.h * (buffer - 1)) {
  728. this.shiftRow(true);
  729. } else if (tlViewPort.y < -this.tileSize.h * buffer) {
  730. this.shiftRow(false);
  731. } else {
  732. shifted = false;
  733. }
  734. if (shifted) {
  735. if(this.useHighSpeed){
  736. this.moveGriddedTiles();
  737. }else{
  738. this.timerId = window.setTimeout(this._moveGriddedTiles, 0);
  739. }
  740. } else {
  741. //tiles have shifted already,so we can do something.
  742. //e.g. We can draw images in those tiles on a canvas, if no image is contained in tile,
  743. //we draw nothing.
  744. }
  745. },
  746. /**
  747. * Method: moveByPx
  748. * 重写父类方法。
  749. */
  750. moveByPx: function(dx, dy) {
  751. this._timeoutId && window.clearTimeout(this._timeoutId);
  752. //记录每次的改变量。
  753. this.changeDx +=dx;
  754. this.changeDy +=dy;
  755. if(this.useHighSpeed){
  756. this.fixPosition();
  757. this.scheduleMoveGriddedTiles();
  758. }
  759. },
  760. /**
  761. * Method: fixPosition
  762. * 平移逻辑。
  763. */
  764. fixPosition: function(){
  765. var tile, tileImg, i, j,
  766. me = this;
  767. //清空webgl
  768. me.canvasContext.viewport(0, 0, me.canvasContext.viewportWidth, me.canvasContext.viewportHeight);
  769. // me.canvasContext.clear(me.canvasContext.COLOR_BUFFER_BIT | me.canvasContext.DEPTH_BUFFER_BIT);
  770. for(i=0; i<this.lenRow; i++){
  771. for(j=0; j<this.lenColumn; j++){
  772. tile = me.grid[i][j];
  773. tileImg = tile.lastImage;
  774. //firefox,即使图片加载失败,complete属性依然为true,故用width和height判断
  775. //IE,图片加载失败时,width为28,height为30,故用complete判断。
  776. if((tileImg != null) && (tile.shouldDraw === true) &&
  777. (tileImg.width > 0 && tileImg.height > 0) &&
  778. tileImg.complete){
  779. var positionX = tile.position.x - me.changeDx;
  780. var positionY = tile.position.y - me.changeDy;
  781. if(tile.lastImage.firstInView){
  782. if(me.getExtent().containsLonLat(tile.bounds.getCenterLonLat())){
  783. tile.lastImage.firstInView = false;
  784. }
  785. else if(me.getExtent().intersectsBounds(tile.bounds)){
  786. tile.setFirstInView();
  787. }
  788. }
  789. me.drawCanvasTile2(tile.lastImage, positionX, positionY, false);
  790. }
  791. }
  792. }
  793. },
  794. /**
  795. * Method: addTile
  796. * Gives subclasses of Grid the opportunity to create an
  797. * OpenLayer.Tile of their choosing. The implementer should initialize
  798. * the new tile and take whatever steps necessary to display it.
  799. *
  800. * Parameters
  801. * bounds - {<SuperMap.Bounds>}
  802. * position - {<SuperMap.Pixel>}
  803. *
  804. * Returns:
  805. * {<SuperMap.Tile>} The added SuperMap.Tile
  806. */
  807. addTile: function(bounds,position) {
  808. // 修改Tile类 todo
  809. if(this.useCanvas){
  810. return new SuperMap.Tile.WebGLImage(this, position, bounds, null, this.tileSize, this.useCanvas)
  811. }else{
  812. var tile = new this.tileClass(
  813. this, position, bounds, null, this.tileSize, this.tileOptions
  814. );
  815. this.events.triggerEvent("addtile", {tile: tile});
  816. return tile;
  817. }
  818. },
  819. /**
  820. * Method: drawCanvasTile
  821. * 当Image加载完成后,将image显示到canvas上。
  822. *
  823. * Parameters:
  824. * image - {<Image>} The tile to draw
  825. * position - {<SuperMap.Pixel>} The position of the tile.
  826. */
  827. drawCanvasTile: function(image, position) {
  828. if (this.dragging) {
  829. return;
  830. }
  831. if(this.inZoom){
  832. image.firstInView = false;
  833. }
  834. this.resetCanvas();
  835. var mapStyle = this.map.layerContainerDiv.style;
  836. var left = parseInt(mapStyle.left),
  837. top = parseInt(mapStyle.top);
  838. //解决ie||移动设备下canvas绘图出错。
  839. if(SuperMap.Browser.name === 'msie'){
  840. var context = {
  841. layer: this,
  842. position: position,
  843. image: image,
  844. mapStyle: mapStyle
  845. };
  846. var _drawCanvasIE = SuperMap.Function.bind(this.drawCanvasIE, context);
  847. window.setTimeout(_drawCanvasIE,100);
  848. }else{
  849. //通过position来绘制图片解决白线问题
  850. this.drawCanvasTile2(image, position.x + left, position.y + top);
  851. }
  852. },
  853. /**
  854. * Method: drawImgData
  855. * canvas上绘制imgdata字符串
  856. *
  857. * Parameters:
  858. * imgData - {<String>} imgdata字符串
  859. * p - {<SuperMap.Pixel>} tile的位置.
  860. */
  861. drawImgData:function(imgData,p){
  862. var mapStyle = this.map.layerContainerDiv.style;
  863. var left = parseInt(mapStyle.left),
  864. top = parseInt(mapStyle.top);
  865. // this.canvasContext.putImageData(imgData, p.x+left, p.y+top);
  866. },
  867. //在ie/移动设备下解决连续绘canvas出错而设置的函数。
  868. drawCanvasIE:function(){
  869. this.layer.drawCanvasTile2(this.image, this.position.x + parseInt(this.mapStyle.left), this.position.y + parseInt(this.mapStyle.top));
  870. },
  871. shaderProgram:null,
  872. /**
  873. * Method: drawCanvasTile2
  874. * 将image显示到canvas上。
  875. *
  876. * Parameters:
  877. * image - {<Image>} 要绘制的图块对象
  878. * positionX - {Number} tile在canvas中的x坐标
  879. * positionY - {Number} tile在canvas中的y坐标
  880. * clear - {boolean} 是否需要重新清除。
  881. */
  882. drawCanvasTile2: function(image, positionX, positionY, clear){
  883. clear = clear || true;
  884. if(image){
  885. var gl = this.canvasContext;
  886. var shaderProgram;
  887. if(true)
  888. {
  889. //初始化渲染器
  890. var fragmentShader = this.getShader(gl, "fragment");
  891. var vertexShader = this.getShader(gl, "vertex");
  892. shaderProgram = gl.createProgram();
  893. gl.attachShader(shaderProgram, vertexShader);
  894. gl.attachShader(shaderProgram, fragmentShader);
  895. gl.linkProgram(shaderProgram);
  896. if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
  897. alert("Could not initialise shaders");
  898. }
  899. gl.useProgram(shaderProgram);
  900. shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
  901. gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
  902. shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
  903. gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
  904. shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
  905. shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
  906. shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
  907. }
  908. //计算瓦片位置
  909. var cubeVertexPositionBuffer00 = gl.createBuffer();
  910. gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer00);
  911. var w = gl.viewportWidth;
  912. var h = gl.viewportHeight;
  913. var nScale;
  914. if(w >= h)
  915. {
  916. nScale = this.tileSize.h/h;
  917. }
  918. else
  919. {
  920. nScale = this.tileSize.h/w;
  921. }
  922. //定义256*256的矩形在当前视图中的矩阵
  923. var vertices = [
  924. -1*nScale, -1*nScale, 0,
  925. 1*nScale, -1*nScale, 0,
  926. 1*nScale, 1*nScale, 0,
  927. -1*nScale, 1*nScale, 0
  928. ];
  929. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
  930. cubeVertexPositionBuffer00.itemSize = 3;
  931. cubeVertexPositionBuffer00.numItems = 4;
  932. var cubeVertexTextureCoordBuffer00 = gl.createBuffer();
  933. gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer00);
  934. var textureCoords = [
  935. 0.0, 0.0,
  936. 1.0, 0.0,
  937. 1.0, 1.0,
  938. 0.0, 1.0
  939. ];
  940. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
  941. cubeVertexTextureCoordBuffer00.itemSize = 2;
  942. cubeVertexTextureCoordBuffer00.numItems = 4;
  943. var cubeVertexIndexBuffer00 = gl.createBuffer();
  944. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer00);
  945. var cubeVertexIndices = [
  946. 0, 1, 2, 0, 2, 3
  947. ];
  948. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
  949. cubeVertexIndexBuffer00.itemSize = 1;
  950. cubeVertexIndexBuffer00.numItems = 6;
  951. //加入图片
  952. var texture = gl.createTexture();
  953. gl.bindTexture(gl.TEXTURE_2D, texture);
  954. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  955. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
  956. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  957. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  958. gl.bindTexture(gl.TEXTURE_2D, null);
  959. gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
  960. var pMatrix = mat4.create();
  961. var mvMatrix = mat4.create();
  962. mat4.perspective(90, gl.viewportWidth / gl.viewportHeight, 1, 100.0, pMatrix);
  963. mat4.identity(mvMatrix);
  964. //进行平移
  965. var x = (positionX - w/2 )*2*nScale/this.tileSize.h + nScale;
  966. var y = (h/2 - positionY)*2*nScale/this.tileSize.h - nScale;
  967. mat4.translate(mvMatrix, [x, y, -1.0]);
  968. gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer00);
  969. gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, cubeVertexPositionBuffer00.itemSize, gl.FLOAT, false, 0, 0);
  970. gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer00);
  971. gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, cubeVertexTextureCoordBuffer00.itemSize, gl.FLOAT, false, 0, 0);
  972. gl.activeTexture(gl.TEXTURE0);
  973. gl.bindTexture(gl.TEXTURE_2D, texture);
  974. gl.uniform1i(shaderProgram.samplerUniform, 0);
  975. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer00);
  976. gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
  977. gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
  978. gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer00.numItems, gl.UNSIGNED_SHORT, 0);
  979. }
  980. },
  981. /**
  982. * Method: getShader
  983. * 初始化着色器
  984. *
  985. * Parameters:
  986. * gl - {<WebGLRenderingContext>} webgl上下文
  987. * name - {String} 可以为片元着色器“fragment”或顶点着色器“vertex”
  988. */
  989. getShader:function(gl,name){
  990. var shader;
  991. var str = "";
  992. if(name == "fragment" )
  993. {
  994. shader = gl.createShader(gl.FRAGMENT_SHADER);
  995. str = "precision mediump float; varying vec2 vTextureCoord; uniform sampler2D uSampler;void main(void){gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));}";
  996. }
  997. else if(name == "vertex" )
  998. {
  999. shader = gl.createShader(gl.VERTEX_SHADER);
  1000. str = "attribute vec3 aVertexPosition; attribute vec2 aTextureCoord; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; varying vec2 vTextureCoord; void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vTextureCoord = aTextureCoord; }";
  1001. }
  1002. gl.shaderSource(shader, str);
  1003. gl.compileShader(shader);
  1004. if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
  1005. alert(gl.getShaderInfoLog(shader));
  1006. return null;
  1007. }
  1008. return shader;
  1009. },
  1010. /**
  1011. * Method: resetCanvas
  1012. * 移动canvas到原点,并清除canvas上的所有东西
  1013. */
  1014. resetCanvas: function() {
  1015. // because the layerContainerDiv has shifted position (for non canvas layers), reposition the canvas.
  1016. if (this.redrawCanvas) {
  1017. this.redrawCanvas = false;
  1018. // clear canvas by reseting the size
  1019. // broken in Chrome 6.0.458.1:
  1020. // http://code.google.com/p/chromium/issues/detail?id=49151
  1021. this.canvas.width = this.map.viewPortDiv.clientWidth;
  1022. this.canvas.height = this.map.viewPortDiv.clientHeight;
  1023. this.canvasContext.viewportWidth = this.canvas.width;
  1024. this.canvasContext.viewportHeight = this.canvas.height;
  1025. //清空webgl
  1026. this.canvasContext.clearColor(0.0, 0.0, 0.0, 0);
  1027. this.canvasContext.enable(this.canvasContext.DEPTH_TEST);
  1028. this.canvasContext.viewport(0, 0, this.canvasContext.viewportWidth, this.canvasContext.viewportHeight);
  1029. this.canvasContext.clear(this.canvasContext.COLOR_BUFFER_BIT | this.canvasContext.DEPTH_BUFFER_BIT);
  1030. if (this.useCanvas) {
  1031. // store the current resolution and canvas position for transition
  1032. this.lastResolution = this.map.getResolution();
  1033. }
  1034. return true;
  1035. }
  1036. return false;
  1037. },
  1038. //重写grid里的initGriddedTiles
  1039. initGriddedTiles:function(bounds) {
  1040. this.isZoomming = false;
  1041. SuperMap.Layer.Grid.prototype.initGriddedTiles.apply(this,arguments);
  1042. this.lenRow = this.grid.length;
  1043. this.lenColumn = this.grid[0].length;
  1044. },
  1045. /**
  1046. * Method: getLayerPxFromLonLat
  1047. * A wrapper for the <SuperMap.Map.getLayerPxFromLonLat()> method,
  1048. * which takes into account that the canvas element has a fixed size and
  1049. * it always moved back to the original position.
  1050. *
  1051. * Parameters:
  1052. * lonlat - {<SuperMap.LonLat>}经纬度
  1053. *
  1054. * Returns:
  1055. * {<SuperMap.Pixel>}像素点
  1056. */
  1057. getLayerPxFromLonLat: function(lonlat) {
  1058. return this.usesCanvas ? this.map.getPixelFromLonLat(lonlat) :
  1059. this.map.getLayerPxFromLonLat(lonlat);
  1060. },
  1061. /**
  1062. * Method: getLayerPxFromLonLat
  1063. * A wrapper for the <SuperMap.Map.getViewPortPxFromLayerPx()> method.
  1064. *
  1065. * Parameters:
  1066. * layerPx - {<SuperMap.Pixel>}
  1067. *
  1068. * Returns:
  1069. * {<SuperMap.Pixel>}
  1070. */
  1071. getViewPortPxFromLayerPx: function(layerPx) {
  1072. return this.useCanvas ? layerPx : this.map.getViewPortPxFromLayerPx(layerPx);
  1073. },
  1074. /**
  1075. * Method: getURL
  1076. * 根据瓦片的bounds获取URL。
  1077. *
  1078. * Parameters:
  1079. * bounds - {<SuperMap.Bounds>} 瓦片的bounds。
  1080. *
  1081. * Returns:
  1082. * {String} 瓦片的URL。
  1083. */
  1084. getURL: function (bounds) {
  1085. var me = this,
  1086. xyz;
  1087. bounds = me.adjustBounds(bounds);
  1088. xyz = me.getXYZ(bounds);
  1089. return me.getTileUrl(xyz);
  1090. },
  1091. /**
  1092. * Method: getXYZ
  1093. * 根据瓦片的bounds获取xyz值。
  1094. *
  1095. * Parameters:
  1096. * bounds - {<SuperMap.Bounds>} 瓦片的bounds。
  1097. *
  1098. * Returns:
  1099. * {Object} 一组键值对,表示瓦片X, Y, Z方向上的索引。
  1100. */
  1101. getXYZ: function (bounds) {
  1102. var me = this,
  1103. x, y, z,
  1104. map = me.map,
  1105. res = map.getResolution(),
  1106. tOrigin = me.getTileOrigin(),
  1107. tileSize = me.tileSize;
  1108. x = Math.round((bounds.left - tOrigin.lon) / (res * tileSize.w));
  1109. y = Math.round((tOrigin.lat - bounds.top) / (res * tileSize.h));
  1110. z = map.getZoom();
  1111. return {"x": x, "y": y, "z": z};
  1112. },
  1113. /**
  1114. * Method: getMemoryImg
  1115. * 根据瓦片的bounds获取内存中该记录的image。
  1116. *
  1117. * Parameters:
  1118. * bounds - {<SuperMap.Bounds>} 瓦片的bounds。
  1119. *
  1120. * Returns:
  1121. * {Object} image对象,不存在返回null
  1122. */
  1123. getMemoryImg: function(bounds){
  1124. var me = this, key = me.getXYZ(bounds);
  1125. key = "x" + key.x + "y" + key.y + "z" + key.z;
  1126. return me.memoryImg[key];
  1127. },
  1128. /**
  1129. * Method: addMemoryImg
  1130. * 记录瓦片bounds和对应的图片信息。
  1131. *
  1132. * Parameters:
  1133. * bounds - {<SuperMap.Bounds>} 瓦片的bounds。
  1134. * image - {<Image>} 瓦片对应的图片信息
  1135. *
  1136. */
  1137. addMemoryImg:function(bounds, image, context){
  1138. var me = this;// key = me.getXYZ(bounds);
  1139. if(me.bufferImgCount == 0)
  1140. return;
  1141. var newImgTag = context.newImgTag;
  1142. if(newImgTag&&newImgTag!=""){
  1143. //删除缓存图片
  1144. if(me.memoryKeys.length >= me.bufferImgCount){
  1145. var keyDel = me.memoryKeys.shift();
  1146. me.memoryImg[keyDel] = null;
  1147. delete me.memoryImg[keyDel];
  1148. }
  1149. var keys = newImgTag.split("_");
  1150. var key = "x" + keys[0] + "y" + keys[1] + "z" + keys[2];
  1151. //缓存图片并保存索引。
  1152. me.memoryImg[key] = image;
  1153. me.memoryKeys.push(key);
  1154. }
  1155. },
  1156. /**
  1157. * Method: initResolutions
  1158. * 初始化Resolutions数组。(重写基类方法)
  1159. */
  1160. initResolutions: function () {
  1161. // 我们想要得到resolutions,以下是我们的策略:
  1162. // 1. 如果在layer配置中定义了resolutions和scales,使用它们,
  1163. // 2. 如果在layer配置中定义resolutions,使用它,
  1164. // 3. 否则,如果在layer配置中定义scales,那么从这些scales中得出resolutions,
  1165. // 4. 再者,试图从在layer配置中设置的 maxResolution,minResolution, numZoomLevels, maxZoomLevel 计算出resolutions,
  1166. // 5. 如果在map中设置了resolutions和scales,使用它们,
  1167. // 6. 如果我们仍然没有获得resolutions,并且resolutions在map中已经定义了,使用它们,
  1168. // 7. 否则,如果scales在map中定义了,那么从scales中得出resolutions,
  1169. // 8. 再者,试图从在map中设置的maxResolution, minResolution, numZoomLevels, maxZoomLevel 计算出resolutions。
  1170. var me = this,
  1171. i, len, p, startZoomLevel,
  1172. props = {},
  1173. alwaysInRange = true;
  1174. //如果在layer中定义了resolutions和scales,直接使用layer的resolutions和scales,并且通过它们计算出
  1175. //maxResolution, minResolution, numZoomLevels, maxScale和minScale
  1176. if (me.resolutions && me.scales) {
  1177. var len = me.resolutions.length;
  1178. me.resolutions.sort(function(a, b) {
  1179. return (b - a);
  1180. });
  1181. if (!me.maxResolution) {
  1182. me.maxResolution = me.resolutions[0];
  1183. }
  1184. if (!me.minResolution) {
  1185. me.minResolution = me.resolutions[len-1];
  1186. }
  1187. me.scales.sort(function(a, b) {
  1188. return (a - b);
  1189. });
  1190. if (!me.maxScale) {
  1191. me.maxScale = me.scales[len-1];
  1192. }
  1193. if (!me.minScale) {
  1194. me.minScale = me.scales[0];
  1195. }
  1196. me.numZoomLevels = len;
  1197. return;
  1198. }
  1199. // 从layer的配置中获得计算resolutions的数据。
  1200. for (i = 0, len = me.RESOLUTION_PROPERTIES.length; i < len; i++) {
  1201. p = me.RESOLUTION_PROPERTIES[i];
  1202. props[p] = me.options[p];
  1203. if (alwaysInRange && me.options[p]) {
  1204. alwaysInRange = false;
  1205. }
  1206. }
  1207. if (me.alwaysInRange == null) {
  1208. me.alwaysInRange = alwaysInRange;
  1209. }
  1210. // 如果没有得到resolutions,利用scales计算resolutions。
  1211. if (props.resolutions == null) {
  1212. props.resolutions = me.resolutionsFromScales(props.scales);
  1213. }
  1214. // 如果仍没有得到resolutions,利用layer配置中设置的
  1215. //maxResolution,minResolution, numZoomLevels, maxZoomLevel 计算出resolutions
  1216. if (props.resolutions == null) {
  1217. props.resolutions = me.calculateResolutions(props);
  1218. }
  1219. //如果没有从layer的配置数据中获得resolutions,并且map中同时设置了resolutions和scales,直接使用它们,
  1220. //并且通过它们计算出maxResolution, minResolution, numZoomLevels, maxScale和minScale
  1221. if (me.map.resolutions && me.map.scales) {
  1222. me.resolutions = me.map.resolutions;
  1223. me.scales = me.map.scales;
  1224. var len = me.resolutions.length;
  1225. me.resolutions.sort(function(a, b) {
  1226. return (b - a);
  1227. });
  1228. if (!me.maxResolution) {
  1229. me.maxResolution = me.resolutions[0];
  1230. }
  1231. if (!me.minResolution) {
  1232. me.minResolution = me.resolutions[len-1];
  1233. }
  1234. me.scales.sort(function(a, b) {
  1235. return (a - b);
  1236. });
  1237. if (!me.maxScale) {
  1238. me.maxScale = me.scales[len-1];
  1239. }
  1240. if (!me.minScale) {
  1241. me.minScale = me.scales[0];
  1242. }
  1243. me.numZoomLevels = len;
  1244. return;
  1245. }
  1246. //如果此时仍没有计算出resolutions,那么先从baselayer上获取,之后从map中获得(方法同上),最后再计算。
  1247. if (props.resolutions == null) {
  1248. for (i = 0, len = me.RESOLUTION_PROPERTIES.length; i<len; i++) {
  1249. p = me.RESOLUTION_PROPERTIES[i];
  1250. props[p] = me.options[p] != null ?
  1251. me.options[p] : me.map[p];
  1252. }
  1253. if (props.resolutions == null) {
  1254. props.resolutions = me.resolutionsFromScales(props.scales);
  1255. }
  1256. if (props.resolutions == null) {
  1257. if(me.map.baseLayer!=null){
  1258. props.resolutions = me.map.baseLayer.resolutions;
  1259. }
  1260. }
  1261. if (props.resolutions == null) {
  1262. props.resolutions = me.calculateResolutions(props);
  1263. }
  1264. }
  1265. var maxRes;
  1266. if (me.options.maxResolution && me.options.maxResolution !== "auto") {
  1267. maxRes = me.options.maxResolution;
  1268. }
  1269. if (me.options.minScale) {
  1270. maxRes = SuperMap.Util.getResolutionFromScaleDpi(me.options.minScale, me.dpi, me.units, me.datumAxis);
  1271. }
  1272. var minRes;
  1273. if (me.options.minResolution && me.options.minResolution !== "auto") {
  1274. minRes = me.options.minResolution;
  1275. }
  1276. if (me.options.maxScale) {
  1277. minRes = SuperMap.Util.getResolutionFromScaleDpi(me.options.maxScale, me.dpi, me.units, me.datumAxis);
  1278. }
  1279. if (props.resolutions) {
  1280. props.resolutions.sort(function(a, b) {
  1281. return (b - a);
  1282. });
  1283. if (!maxRes) {
  1284. maxRes = props.resolutions[0];
  1285. }
  1286. if (!minRes) {
  1287. var lastIdx = props.resolutions.length - 1;
  1288. minRes = props.resolutions[lastIdx];
  1289. }
  1290. }
  1291. me.resolutions = props.resolutions;
  1292. if (me.resolutions) {
  1293. len = me.resolutions.length;
  1294. me.scales = [len];
  1295. if(me.map.baseLayer){
  1296. startZoomLevel = this.calculateResolutionsLevel(me.resolutions);
  1297. }
  1298. else{
  1299. startZoomLevel = 0;
  1300. }
  1301. for (i = startZoomLevel; i < len + startZoomLevel; i++) {
  1302. me.scales[i] = SuperMap.Util.getScaleFromResolutionDpi(me.resolutions[i- startZoomLevel], me.dpi, me.units, me.datumAxis);
  1303. }
  1304. me.numZoomLevels = len;
  1305. }
  1306. me.minResolution = minRes;
  1307. if (minRes) {
  1308. me.maxScale = SuperMap.Util.getScaleFromResolutionDpi(minRes, me.dpi, me.units, me.datumAxis);
  1309. }
  1310. me.maxResolution = maxRes;
  1311. if (maxRes) {
  1312. me.minScale = SuperMap.Util.getScaleFromResolutionDpi(maxRes, me.dpi, me.units, me.datumAxis);
  1313. }
  1314. },
  1315. /**
  1316. * Method: calculateResolutionsLevel
  1317. * 根据resolutions数组计算scale数组。
  1318. *
  1319. * Parameters:
  1320. * resolutions - {Array({Number})}resolutions数组
  1321. */
  1322. calculateResolutionsLevel: function(resolutions){
  1323. var me = this, j, len, resolution,
  1324. baseLayerResolutions;
  1325. baseLayerResolutions = me.map.baseLayer.resolutions;
  1326. len = baseLayerResolutions.length;
  1327. resolution = resolutions[0];
  1328. for(j=0; j<len; j++){
  1329. if(resolution == baseLayerResolutions[j]){
  1330. return j;
  1331. }
  1332. }
  1333. return 0;
  1334. },
  1335. /**
  1336. * Method: resolutionsFromScales
  1337. * 根据scales数组计算resolutions数组。(重写基类方法)
  1338. *
  1339. * Parameters:
  1340. * scales - {Array({Number})}scales数组。
  1341. */
  1342. resolutionsFromScales: function (scales) {
  1343. if (scales == null) {
  1344. return;
  1345. }
  1346. var me = this,
  1347. resolutions, len;
  1348. len = scales.length;
  1349. resolutions = [len];
  1350. for (var i = 0; i < len; i++) {
  1351. resolutions[i] = SuperMap.Util.getResolutionFromScaleDpi(
  1352. scales[i], me.dpi, me.units, me.datumAxis);
  1353. }
  1354. return resolutions;
  1355. },
  1356. /**
  1357. * Method: calculateResolutions
  1358. * 根据已提供的属性计算resolutions数组。(重写基类方法)
  1359. *
  1360. * Parameters:
  1361. * props - {Object}
  1362. *
  1363. * Return:
  1364. * {Array({Number})} resolutions数组.
  1365. */
  1366. calculateResolutions: function (props) {
  1367. var me = this,
  1368. maxResolution = props.maxResolution;
  1369. if (props.minScale != null) {
  1370. maxResolution = SuperMap.Util.getResolutionFromScaleDpi(props.minScale, me.dpi, me.units, me.datumAxis);
  1371. } else if (maxResolution == "auto" && me.maxExtent != null) {
  1372. var viewSize, wRes, hRes;
  1373. viewSize = me.map.getSize();
  1374. wRes = me.maxExtent.getWidth() / viewSize.w;
  1375. hRes = me.maxExtent.getHeight() / viewSize.h;
  1376. maxResolution = Math.max(wRes, hRes);
  1377. }
  1378. var minResolution = props.minResolution;
  1379. if (props.maxScale != null) {
  1380. minResolution = SuperMap.Util.getResolutionFromScaleDpi(props.maxScale, me.dpi, me.units, me.datumAxis);
  1381. } else if (props.minResolution == "auto" && me.minExtent != null) {
  1382. var viewSize, wRes, hRes;
  1383. viewSize = me.map.getSize();
  1384. wRes = me.minExtent.getWidth() / viewSize.w;
  1385. hRes = me.minExtent.getHeight()/ viewSize.h;
  1386. minResolution = Math.max(wRes, hRes);
  1387. }
  1388. if(typeof maxResolution !== "number" &&
  1389. typeof minResolution !== "number" &&
  1390. this.maxExtent != null) {
  1391. // maxResolution for default grid sets assumes that at zoom
  1392. // level zero, the whole world fits on one tile.
  1393. var tileSize = this.map.getTileSize();
  1394. maxResolution = Math.max(
  1395. this.maxExtent.getWidth() / tileSize.w,
  1396. this.maxExtent.getHeight() / tileSize.h
  1397. );
  1398. }
  1399. var maxZoomLevel = props.maxZoomLevel;
  1400. var numZoomLevels = props.numZoomLevels;
  1401. if (typeof minResolution === "number" &&
  1402. typeof maxResolution === "number" && numZoomLevels === undefined) {
  1403. var ratio = maxResolution / minResolution;
  1404. numZoomLevels = Math.floor(Math.log(ratio) / Math.log(2)) + 1;
  1405. } else if (numZoomLevels === undefined && maxZoomLevel != null) {
  1406. numZoomLevels = maxZoomLevel + 1;
  1407. }
  1408. if (typeof numZoomLevels !== "number" || numZoomLevels <= 0 ||
  1409. (typeof maxResolution !== "number" &&
  1410. typeof minResolution !== "number")) {
  1411. return;
  1412. }
  1413. var resolutions = [numZoomLevels];
  1414. var base = 2;
  1415. if (typeof minResolution == "number" && typeof maxResolution == "number") {
  1416. base = Math.pow(
  1417. (maxResolution / minResolution),
  1418. (1 / (numZoomLevels - 1))
  1419. );
  1420. }
  1421. if (typeof maxResolution === "number") {
  1422. for (var i = 0; i < numZoomLevels; i++) {
  1423. resolutions[i] = maxResolution / Math.pow(base, i);
  1424. }
  1425. } else {
  1426. for (i = 0; i < numZoomLevels; i++) {
  1427. resolutions[numZoomLevels - 1 - i] =
  1428. minResolution * Math.pow(base, i);
  1429. }
  1430. }
  1431. return resolutions;
  1432. },
  1433. CLASS_NAME: "SuperMap.Layer.WebGLLayer"
  1434. });