mvt.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /* MVT加载类 作者: 木遥(微信: http://marsgis.cn/weixin.html ) */
  2. ; (function (window) {
  3. function MvtImageryProvider (options) {
  4. options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT)
  5. this.options = options
  6. this._tileWidth = Cesium.defaultValue(options.tileWidth, 512)
  7. this._tileHeight = Cesium.defaultValue(options.tileHeight, 512)
  8. this._minimumLevel = Cesium.defaultValue(options.minimumLevel, 0)
  9. this._maximumLevel = Cesium.defaultValue(options.maximumLevel, 18)
  10. if (options.rectangle && options.rectangle.xmin && options.rectangle.xmax && options.rectangle.ymin && options.rectangle.ymax) {
  11. var xmin = options.rectangle.xmin
  12. var xmax = options.rectangle.xmax
  13. var ymin = options.rectangle.ymin
  14. var ymax = options.rectangle.ymax
  15. options.rectangle = Cesium.Rectangle.fromDegrees(xmin, ymin, xmax, ymax)
  16. }
  17. this._tilingScheme = Cesium.defaultValue(options.tilingScheme, new Cesium.WebMercatorTilingScheme({ ellipsoid: options.ellipsoid }))
  18. this._rectangle = Cesium.defaultValue(options.rectangle, this._tilingScheme.rectangle)
  19. this._rectangle = Cesium.Rectangle.intersection(this._rectangle, this._tilingScheme.rectangle)
  20. this._hasAlphaChannel = Cesium.defaultValue(options.hasAlphaChannel, true)
  21. this._errorEvent = new Cesium.Event()
  22. this._readyPromise = Cesium.when.resolve(true)
  23. this._credit = undefined
  24. this._ready = true
  25. //mvt相关的处理
  26. if (!window.ol) {
  27. throw new DeveloperError('请引入Openlayers类库!')
  28. }
  29. this._ol = window.ol
  30. this._mvtParser = new this._ol.format.MVT()
  31. this._key = Cesium.defaultValue(options.key, '')
  32. this._url = Cesium.defaultValue(options.url, '')
  33. if (options.styleConfig) {
  34. //(glStyle, sources, resolutions = defaultResolutions, spriteData, spriteImageUrl, getFonts)
  35. this._styleClass = window.olms.stylefunction(options.styleConfig, options.styleConfig.sources, "", null, null)
  36. // this._url = options.styleConfig.tiles[0]
  37. }
  38. else if (options.style) {
  39. switch (options.style) {
  40. case 'mapbox-streets-v6':
  41. this._styleClass = new mars3d.MapboxStreetsV6()
  42. break
  43. default:
  44. this._styleClass = options.style
  45. break
  46. }
  47. }
  48. var sw = this._tilingScheme._rectangleSouthwestInMeters
  49. var ne = this._tilingScheme._rectangleNortheastInMeters
  50. var mapExtent = [sw.x, sw.y, ne.x, ne.y]
  51. this._resolutions = ol.tilegrid.resolutionsFromExtent(mapExtent, this._maximumLevel, this._tileWidth)
  52. this._pixelRatio = 1
  53. this._transform = [0.125, 0, 0, 0.125, 0, 0]
  54. this._replays = ['Default', 'Image', 'Polygon', 'LineString', 'Text']
  55. this._tileQueue = new Cesium.TileReplacementQueue()
  56. this._cacheSize = 1000
  57. }
  58. Object.defineProperties(MvtImageryProvider.prototype, {
  59. proxy: {
  60. get: function () {
  61. return undefined
  62. },
  63. },
  64. tileWidth: {
  65. get: function () {
  66. return this._tileWidth
  67. },
  68. },
  69. tileHeight: {
  70. get: function () {
  71. return this._tileHeight
  72. },
  73. },
  74. maximumLevel: {
  75. get: function () {
  76. return undefined
  77. },
  78. },
  79. minimumLevel: {
  80. get: function () {
  81. return undefined
  82. },
  83. },
  84. tilingScheme: {
  85. get: function () {
  86. return this._tilingScheme
  87. },
  88. },
  89. rectangle: {
  90. get: function () {
  91. return this._tilingScheme.rectangle
  92. },
  93. },
  94. tileDiscardPolicy: {
  95. get: function () {
  96. return undefined
  97. },
  98. },
  99. errorEvent: {
  100. get: function () {
  101. return this._errorEvent
  102. },
  103. },
  104. ready: {
  105. get: function () {
  106. return true
  107. },
  108. },
  109. readyPromise: {
  110. get: function () {
  111. return this._readyPromise
  112. },
  113. },
  114. credit: {
  115. get: function () {
  116. return undefined
  117. },
  118. },
  119. hasAlphaChannel: {
  120. get: function () {
  121. return true
  122. },
  123. },
  124. })
  125. MvtImageryProvider.prototype.getTileCredits = function (x, y, level) {
  126. return undefined
  127. }
  128. MvtImageryProvider.prototype.pickFeatures = function (x, y, level, longitude, latitude) {
  129. return undefined
  130. }
  131. MvtImageryProvider.prototype.requestImage = function (x, y, level, request) {
  132. var cacheTile = findTileInQueue(x, y, level, this._tileQueue)
  133. if (cacheTile != undefined) {
  134. return cacheTile
  135. } else {
  136. var that = this
  137. var url = this._url
  138. var reverseY = this._tilingScheme.getNumberOfYTilesAtLevel(level) - y - 1
  139. url = url.replace('{x}', x).replace('{y}', y).replace('{reverseY}', reverseY).replace('{z}', level).replace('{k}', this._key)
  140. var resource = Cesium.Resource.createIfNeeded(url)
  141. return resource
  142. .fetchArrayBuffer()
  143. .then(function (arrayBuffer) {
  144. var canvas = document.createElement('canvas')
  145. canvas.width = that._tileWidth
  146. canvas.height = that._tileHeight
  147. var vectorContext = canvas.getContext('2d')
  148. var features = that._mvtParser.readFeatures(arrayBuffer)
  149. var styleFun = that._styleClass.getStyle()
  150. var extent = [0, 0, 4096, 4096]
  151. var _replayGroup = new ol.render.canvas.ReplayGroup(0, extent, 8, true, 100)
  152. for (var i = 0; i < features.length; i++) {
  153. var feature = features[i]
  154. var styles = styleFun(features[i], that._resolutions[level])
  155. for (var j = 0; j < styles.length; j++) {
  156. ol.renderer.vector.renderFeature_(_replayGroup, feature, styles[j], 16)
  157. }
  158. }
  159. _replayGroup.finish()
  160. _replayGroup.replay(vectorContext, that._pixelRatio, that._transform, 0, {}, that._replays, true)
  161. if (that._tileQueue.count > that._cacheSize) {
  162. trimTiles(that._tileQueue, that._cacheSize / 2)
  163. }
  164. canvas.xMvt = x
  165. canvas.yMvt = y
  166. canvas.zMvt = level
  167. that._tileQueue.markTileRendered(canvas)
  168. delete _replayGroup
  169. _replayGroup = null
  170. return canvas
  171. })
  172. .otherwise(function (error) {
  173. return undefined
  174. })
  175. }
  176. }
  177. function findTileInQueue (x, y, level, tileQueue) {
  178. var item = tileQueue.head
  179. while (item != undefined && !(item.xMvt == x && item.yMvt == y && item.zMvt == level)) {
  180. item = item.replacementNext
  181. }
  182. return item
  183. }
  184. function removeQueue (tileReplacementQueue, item) {
  185. var previous = item.replacementPrevious
  186. var next = item.replacementNext
  187. if (item === tileReplacementQueue._lastBeforeStartOfFrame) {
  188. tileReplacementQueue._lastBeforeStartOfFrame = next
  189. }
  190. if (item === tileReplacementQueue.head) {
  191. tileReplacementQueue.head = next
  192. } else {
  193. previous.replacementNext = next
  194. }
  195. if (item === tileReplacementQueue.tail) {
  196. tileReplacementQueue.tail = previous
  197. } else {
  198. next.replacementPrevious = previous
  199. }
  200. item.replacementPrevious = undefined
  201. item.replacementNext = undefined
  202. --tileReplacementQueue.count
  203. }
  204. function trimTiles (tileQueue, maximumTiles) {
  205. var tileToTrim = tileQueue.tail
  206. while (tileQueue.count > maximumTiles && Cesium.defined(tileToTrim)) {
  207. var previous = tileToTrim.replacementPrevious
  208. removeQueue(tileQueue, tileToTrim)
  209. delete tileToTrim
  210. tileToTrim = null
  211. tileToTrim = previous
  212. }
  213. }
  214. class MvtLayer extends mars3d.layer.BaseTileLayer {
  215. _addedHook () {
  216. let styleUrl = this.options.style
  217. if (mars3d.Util.isString(styleUrl) && styleUrl.endsWith(".json")) {
  218. this.getPbfStyle(styleUrl).then((data) => {
  219. if (this.isAdded) {
  220. super._addedHook();
  221. }
  222. });
  223. } else {
  224. super._addedHook();
  225. }
  226. }
  227. //构建ImageryProvider
  228. _createImageryProvider (options) {
  229. return createImageryProvider(options)
  230. }
  231. //取样式数据
  232. getPbfStyle (styleUrl) {
  233. return mars3d.Resource.fetchJson({
  234. url: styleUrl,
  235. queryParameters: {
  236. access_token: this.options.key || "mars3d"
  237. }
  238. }).then((json) => {
  239. this.options.styleConfig = json
  240. })
  241. .otherwise(function (error) {
  242. console.log("加载样式出错", error);
  243. });
  244. }
  245. }
  246. function createImageryProvider (options) {
  247. return new MvtImageryProvider(options)
  248. }
  249. MvtLayer.createImageryProvider = createImageryProvider
  250. //注册下
  251. const layerType = 'mvt' //图层类型
  252. mars3d.LayerUtil.register(layerType, MvtLayer)
  253. mars3d.LayerUtil.registerImageryProvider(layerType, createImageryProvider)
  254. //对外接口
  255. window.mars3d.provider.MvtImageryProvider = MvtImageryProvider
  256. window.mars3d.layer.MvtLayer = MvtLayer
  257. })(window)