CrImageServerLayer.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. /**
  2. * 创建者:王成
  3. * 操作系统:MAC
  4. * 创建日期:2023年1月30日
  5. * 描述:通过矩形渲染tile,从而达到渲染图片可以浮动在实景三维上面的效果
  6. */
  7. /* 扩展系统Date属性Format 用于格式化日期 yyMMdd HH:ss:mm */
  8. Date.prototype.Format = function(fmt) { // author: meizz
  9. var o = {
  10. "M+": this.getMonth() + 1, // 月份
  11. "d+": this.getDate(), // 日
  12. "h+": this.getHours(), // 小时
  13. "m+": this.getMinutes(), // 分
  14. "s+": this.getSeconds(), // 秒
  15. "q+": Math.floor((this.getMonth() + 3) / 3), // 季度
  16. "S": this.getMilliseconds() // 毫秒
  17. };
  18. if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
  19. for (var k in o)
  20. if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : ((
  21. "00" + o[k]).substr(("" + o[k]).length)));
  22. return fmt;
  23. }
  24. /* 引入Cesium */
  25. // import * as Cesium from 'cesium';
  26. // import Worker from '../../../public/worker/download.js?worker';
  27. /* 创建类 */
  28. class CrImageServerLayer {
  29. /**
  30. * 构造函数
  31. * @param {Cesium.Viewer} options.viewer 地图视图容器
  32. * @param {String} options.url 服务地址
  33. * @param {Number} options.opacity 图层透明度[0.0~1.0] [默认0.3]
  34. */
  35. constructor({
  36. viewer,
  37. url,
  38. opacity = 0.75,
  39. show = true,
  40. } = {}) {
  41. /* 地图视图 外部传入 必须参数 */
  42. this._viewer = viewer;
  43. /* 服务地址 外部传入 */
  44. this._url = url;
  45. /* 透明度 外部传入 */
  46. this._opacity = opacity;
  47. /* 图层随机标识 */
  48. this._renderName = this._guid();
  49. /* 实体集合 */
  50. /* 用DataSource 方式 以便进行多图层管理 */
  51. let dataSource = new Cesium.CustomDataSource(this._renderName);
  52. this._viewer.dataSources.add(dataSource);
  53. this._entities = dataSource.entities;
  54. /* 渲染集合 */
  55. this._renderEntities = new Map();
  56. /* 是否渲染标志 */
  57. this._isUpdateTile = show;
  58. /* 是否输出测试信息 */
  59. this._isDebug = false;
  60. /* 初始化 */
  61. this._init();
  62. }
  63. /**
  64. * 初始化
  65. */
  66. _init() {
  67. let _self = this;
  68. /* 创建服务提供者 */
  69. this._provider = new Cesium.ArcGisMapServerImageryProvider({
  70. url: _self._url,
  71. })
  72. /* 激活服务提供者 注册刷帧事件 */
  73. this._provider.readyPromise.then(function(result) {
  74. /* 服务提供者的数据范围 */
  75. _self._rectangle = _self._provider.rectangle;
  76. /* 输出调试信息 */
  77. if (_self._isDebug) _self._printDebug();
  78. /* 注册事件 */
  79. _self._viewer.scene.postRender.addEventListener(() => {
  80. if (_self._isUpdateTile) {
  81. /* 设置运行标志为false 等待计算完成 */
  82. _self._isUpdateTile = false;
  83. /* 投影瓦片集合 */
  84. _self._renderTiles();
  85. }
  86. });
  87. })
  88. }
  89. /**
  90. * 生成GUID随机数
  91. */
  92. _guid() {
  93. function S4() {
  94. return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  95. }
  96. return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
  97. }
  98. /**
  99. * 输出调试信息
  100. */
  101. _printDebug() {
  102. /* 数据提供者的切片方案 */
  103. let tiling = this._provider.tilingScheme;
  104. /* WGS84坐标系的切片方案 */
  105. let tiling84 = new Cesium.GeographicTilingScheme();
  106. /* 绘制数据提供者的数据范围 */
  107. this._drawDebugRectangle(this._rectangle, Cesium.Color.GREEN);
  108. /* 根据行列号和等级创建调试矩形 */
  109. let rect = tiling84.tileXYToRectangle(1696, 312, 10);
  110. /* 绘制调试矩形 */
  111. // this._drawDebugRectangle(rect, Cesium.Color.YELLOW);
  112. // let rect11 = Cesium.Rectangle.subsection(rect, 0, 0, 0.5, 0.5);
  113. // let rect12 = Cesium.Rectangle.subsection(rect, 0.5, 0, 1.0, 0.5);
  114. // let rect21 = Cesium.Rectangle.subsection(rect, 0, 0.5, 0.5, 1.0);
  115. // let rect22 = Cesium.Rectangle.subsection(rect, 0.5, 0.5, 1.0, 1.0);
  116. // this._drawDebugRectangle(rect11, Cesium.Color.RED);
  117. // this._drawDebugRectangle(rect12, Cesium.Color.GREEN);
  118. // this._drawDebugRectangle(rect21, Cesium.Color.BLUE);
  119. // this._drawDebugRectangle(rect22, Cesium.Color.WHITE);
  120. }
  121. /**
  122. * 绘制调试矩形
  123. * @param {Cesium.Rectangle} rectangle 绘制的矩形
  124. * @param {Cesium.Color} color 矩形边框颜色
  125. */
  126. _drawDebugRectangle(rectangle, color) {
  127. /* 计算矩形的外包范围 */
  128. let positions = this._calculateRectangleOutlineCoordinates(rectangle);
  129. /* 创建矩形实体 */
  130. let rectEntity = new Cesium.Entity({
  131. name: this._renderName,
  132. polyline: {
  133. positions: positions,
  134. material: color,
  135. width: 10,
  136. clampToGround: true, //开启贴地 如果有模型则贴模型
  137. }
  138. });
  139. /* 加入数据集 */
  140. this._entities.add(rectEntity);
  141. }
  142. /**
  143. * 输出消息
  144. * @param {Object} res
  145. */
  146. _console(...rest) {
  147. if (this._isDebug)
  148. console.log('===' + new Date().Format('yyyy-MM-dd HH:mm:ss') + '>>>', rest);
  149. }
  150. /**
  151. * 渲染瓦片集合
  152. */
  153. _renderTiles() {
  154. let _self = this;
  155. /* 获取当前视图渲染的瓦片集合 */
  156. let tilesToRender = this._viewer.scene.globe._surface._tilesToRender;
  157. if (tilesToRender === undefined || tilesToRender.length === 0) {
  158. this._isUpdateTile = true;
  159. return;
  160. } else {
  161. new Promise((resolve, reject) => {
  162. /* 对瓦片数组按照level进行排序 以保证后续瓦片重投影时的重叠移除无误 */
  163. tilesToRender.sort(function(obj1, obj2) {
  164. let level1 = parseInt(obj1.level);
  165. let level2 = parseInt(obj2.level);
  166. return level1 - level2;
  167. })
  168. /* 返回排序后的渲染瓦片数据集 开始异步计算 */
  169. resolve(tilesToRender);
  170. }).then(tiles => {
  171. /* 异步重投影瓦片数据集 */
  172. _self._asyncProjectionTiles(tiles);
  173. })
  174. }
  175. }
  176. /**
  177. * 根据行列和等级生成key
  178. * @param {Number} x 行
  179. * @param {Number} y 列
  180. * @param {Number} level 等级
  181. */
  182. _createKey(x, y, level) {
  183. let key = `${this._renderName}_${x}_${y}_${level}`;
  184. return key;
  185. }
  186. /**
  187. * 投影瓦片集合
  188. * @param {Object} tiles 原始渲染瓦片集合
  189. */
  190. _asyncProjectionTiles(tiles) {
  191. let renderTiles = [];
  192. /* 循环投影 */
  193. for (let tile of tiles) {
  194. /* 对单个瓦片进行重投影 */
  195. let proTiles = this._projectionTile(tile);
  196. for (let proTile of proTiles) {
  197. /* 瓦片实体唯一标识 */
  198. let key = this._createKey(proTile.x, proTile.y, proTile.level);
  199. /* 查找瓦片是否已经存在 存在则过滤 以免重复存在 */
  200. let subTile = renderTiles.find(obj => {
  201. return obj.x === proTile.x && obj.y === proTile.y;
  202. })
  203. if (subTile === undefined) {
  204. /* 重投影瓦片范围与数据范围的叠合计算 */
  205. let isExists = false;
  206. for (let eTile of renderTiles) {
  207. if (Cesium.Rectangle.intersection(eTile.rectangle, proTile.rectangle)) {
  208. /* 追加子集 方便后期进行层级处理 */
  209. eTile.childTiles.push(key);
  210. isExists = true;
  211. break;
  212. }
  213. }
  214. /* 加入渲染集合 */
  215. if (!isExists) {
  216. renderTiles.push({
  217. key: key,
  218. x: proTile.x,
  219. y: proTile.y,
  220. level: proTile.level,
  221. rectangle: proTile.rectangle,
  222. childTiles: [],
  223. });
  224. }
  225. }
  226. }
  227. }
  228. /* 清理低层级元素 */
  229. let i = renderTiles.length;
  230. let appendTiles = [];
  231. while (i--) {
  232. let findTile = renderTiles[i];
  233. if (findTile.childTiles.length >= 1) {
  234. /* 创建高层级的瓦片 */
  235. let tiles = this._createFourTiles(findTile);
  236. for (let tile of tiles) {
  237. appendTiles.push(tile);
  238. }
  239. /* 如果存在高层级 则删除低层级 */
  240. renderTiles.splice(i, 1);
  241. }
  242. }
  243. /* 将四叉树追加的层级数据加入到渲染集合中 */
  244. for (let appendTile of appendTiles) {
  245. renderTiles.push(appendTile);
  246. }
  247. /* 对数组进行排序 */
  248. renderTiles.sort(function(obj1, obj2) {
  249. let level1 = parseInt(obj1.level);
  250. let level2 = parseInt(obj2.level);
  251. return level1 - level2;
  252. })
  253. /* 渲染数据到视图中 */
  254. this._renderTilesToViewer(renderTiles);
  255. }
  256. /**
  257. * 根据矩形和登记查询高一等级的行列号
  258. * @param {Cesium.Rectangle} rectangle
  259. */
  260. _createTileByRectangleAndLevel(rectangle, level) {
  261. /* 获取矩形中心点 */
  262. let center = Cesium.Rectangle.center(rectangle);
  263. /* 新层级 */
  264. let nLevel = parseInt(level) + 1;
  265. /* 查询高一层级的行列号 */
  266. let query = this._provider.tilingScheme.positionToTileXY(center, nLevel);
  267. if (query === undefined) return undefined;
  268. /* 返回结果 */
  269. return {
  270. key: this._createKey(query.x, query.y, nLevel),
  271. x: query.x,
  272. y: query.y,
  273. level: nLevel,
  274. rectangle: rectangle,
  275. childTiles: [],
  276. }
  277. }
  278. /**
  279. * 创建四个高层级的瓦片
  280. * @param {Object} tile 当前瓦片
  281. */
  282. _createFourTiles(tile) {
  283. let rects = [];
  284. let results = [];
  285. let rectangle = tile.rectangle;
  286. /* 将该矩形按照四叉树规则分割为4个高层级的矩形 */
  287. rects.push(Cesium.Rectangle.subsection(rectangle, 0, 0, 0.5, 0.5));
  288. rects.push(Cesium.Rectangle.subsection(rectangle, 0.5, 0, 1.0, 0.5));
  289. rects.push(Cesium.Rectangle.subsection(rectangle, 0, 0.5, 0.5, 1.0));
  290. rects.push(Cesium.Rectangle.subsection(rectangle, 0.5, 0.5, 1.0, 1.0));
  291. for (let rect of rects) {
  292. /* 判断高层级的矩形是否与谁范围存在交集 */
  293. if (Cesium.Rectangle.intersection(rect, this._rectangle)) {
  294. /* 查询高一层级的Tile */
  295. let newTile = this._createTileByRectangleAndLevel(rect, tile.level);
  296. /* 如果存在加入到返回集合中 */
  297. if (newTile !== undefined) results.push(newTile);
  298. }
  299. }
  300. return results;
  301. }
  302. /**
  303. * 渲染瓦片到视图中
  304. * @param {Object} tiles
  305. */
  306. _renderTilesToViewer(tiles) {
  307. let _self = this;
  308. /* 确定哪些渲染实体已失效 对失效的实体进行清理 */
  309. let deleteKeys = [];
  310. for (let [key, tile] of this._renderEntities) {
  311. let findTile = tiles.find(obj => {
  312. return obj.key === key;
  313. })
  314. if (findTile === undefined) {
  315. deleteKeys.push(key);
  316. }
  317. }
  318. for (let key of deleteKeys) {
  319. /* 移除元素 */
  320. this._renderEntities.delete(key);
  321. /* 移除渲染元素 */
  322. this._entities.removeById(key);
  323. }
  324. /* 对过滤后的数据集进行渲染 */
  325. for (let tile of tiles) {
  326. /* 判断当前渲染的数据是否已经渲染且有效 */
  327. if (!this._renderEntities.has(tile.key)) {
  328. /* 将数据渲染到视图中 */
  329. let entity = this._renderSimpleTileToViewer(tile);
  330. /* 将渲染的数据加入到集合中 */
  331. this._renderEntities.set(tile.key, entity);
  332. /* 创建下载线程 */
  333. let workBlob = new Blob([`(${downloadWorker.toString ()})()`]); // 把函数转成一个自执行函数
  334. // let workBlob = new Blob([downloadWorker.toLocaleString().match(
  335. // /(?:\/\*[\s\S]*?\*\/|\/\/.*?\r?\n|[^{])+\{([\s\S]*)\}$/)[1]]) // 把函数的主体内容拿出来进行转换
  336. let worker = new Worker(URL.createObjectURL(workBlob));
  337. /* 发送下载任务 */
  338. worker.postMessage({
  339. key: tile.key,
  340. url: this._url,
  341. x: tile.x,
  342. y: tile.y,
  343. level: tile.level,
  344. })
  345. /* 接收下载任务 */
  346. worker.onmessage = function(event) {
  347. _self._console(`render x:${event.data.x} y:${event.data.y} level:${event.data.level}`);
  348. /* 判断是否存在 */
  349. let renderEntity = _self._entities.getById(event.data.key);
  350. if (renderEntity !== undefined) {
  351. let key = event.data.key;
  352. const canvas = _self._createCanvas(event.data, event.data.image, _self._isDebug);
  353. renderEntity.rectangle.material = canvas;
  354. }
  355. worker.terminate();
  356. }
  357. }
  358. }
  359. /* 重启计算标志 */
  360. this._isUpdateTile = true;
  361. }
  362. /**
  363. * 渲染单个瓦片到视图中
  364. * @param {Object} tile
  365. */
  366. _renderSimpleTileToViewer(tile) {
  367. /* 创建画布 */
  368. const canvas = this._createCanvas(tile, undefined, this._isDebug);
  369. let bjPositions = this._calculateRectangleOutlineCoordinates(tile
  370. .rectangle);
  371. let tileEntity = new Cesium.Entity({
  372. name: this._renderName,
  373. id: tile.key,
  374. rectangle: {
  375. coordinates: tile.rectangle,
  376. material: canvas,
  377. },
  378. polyline: {
  379. positions: bjPositions,
  380. material: Cesium.Color.YELLOW.withAlpha(this._isDebug ? 1 : 0),
  381. width: 1,
  382. clampToGround: true, //开启贴地 如果有模型则贴模型
  383. }
  384. });
  385. return this._entities.add(tileEntity);
  386. }
  387. /**
  388. * 根据瓦片创建画布
  389. * @param {Object} tile 瓦片
  390. * @param {Object} image 绘制的图片
  391. * @param {boolean} islabel 是否绘制标签
  392. */
  393. _createCanvas(tile, image, islabel) {
  394. /* 获取服务提供者的切片方案 */
  395. let provider = this._provider;
  396. const canvas = document.createElement("canvas");
  397. canvas.width = provider.tileWidth;
  398. canvas.height = provider.tileHeight;
  399. const context = canvas.getContext("2d");
  400. if (image !== undefined) {
  401. context.globalAlpha = this._opacity;
  402. context.drawImage(event.data.image, 0, 0, canvas.width, canvas.height);
  403. }
  404. if (islabel !== undefined && islabel === true) {
  405. context.globalAlpha = 1.0;
  406. /* 创建标签 */
  407. context.font = "20px Arial";
  408. context.textAlign = "center";
  409. context.fillStyle = 'rgba(255,255,0)';
  410. context.strokeStyle = 'rgba(255,255,255,1)';
  411. context.lineWidth = 2;
  412. context.strokeText(`L: ${tile.level}`, 126, 86);
  413. context.fillText(`L: ${tile.level}`, 126, 86);
  414. context.strokeText(`X: ${tile.x}`, 126, 136);
  415. context.fillText(`X: ${tile.x}`, 126, 136);
  416. context.strokeText(`Y: ${tile.y}`, 126, 186);
  417. context.fillText(`Y: ${tile.y}`, 126, 186);
  418. }
  419. /* 返回画布 */
  420. return canvas;
  421. }
  422. /**
  423. * 投影当前瓦片
  424. * @param {Object} tile
  425. */
  426. _projectionTile(tile) {
  427. /* 获取矩形 */
  428. let rectangle = tile._rectangle;
  429. // let imageryLevel = parseInt(tile.level) + 1;
  430. let imageryLevel = parseInt(tile.level);
  431. let mercatorTilingScheme = this._provider.tilingScheme;
  432. let res = [];
  433. /* 先判断当前的切片范围是否与提供者的数据范围有交集 */
  434. let interRectangle = Cesium.Rectangle.intersection(rectangle, this._rectangle);
  435. /* 如果当前计算的瓦片与数据范围无交集 则舍弃 */
  436. if (interRectangle === undefined) return res;
  437. /* 判断北西角点的墨卡托投影瓦片信息 */
  438. let northwestTileCoordinates = mercatorTilingScheme.positionToTileXY(
  439. Cesium.Rectangle.northwest(rectangle),
  440. imageryLevel
  441. );
  442. /* 判断南东角点的墨卡托投影瓦片信息 */
  443. let southeastTileCoordinates = mercatorTilingScheme.positionToTileXY(
  444. Cesium.Rectangle.southeast(rectangle),
  445. imageryLevel
  446. );
  447. /* 根据不同类型分别进行计算 */
  448. if (northwestTileCoordinates !== undefined && southeastTileCoordinates !== undefined) {
  449. for (let i = northwestTileCoordinates.x; i <= southeastTileCoordinates.x; i++) {
  450. for (let j = northwestTileCoordinates.y; j <= southeastTileCoordinates.y; j++) {
  451. let _webRectangle = mercatorTilingScheme.tileXYToRectangle(i, j, imageryLevel);
  452. if (Cesium.Rectangle.intersection(_webRectangle, this._rectangle)) {
  453. res.push({
  454. x: i,
  455. y: j,
  456. level: imageryLevel,
  457. rectangle: _webRectangle,
  458. });
  459. }
  460. }
  461. }
  462. } else if (northwestTileCoordinates !== undefined) {
  463. let _webRectangle = mercatorTilingScheme.tileXYToRectangle(northwestTileCoordinates.x,
  464. northwestTileCoordinates.y,
  465. imageryLevel);
  466. if (Cesium.Rectangle.intersection(_webRectangle, this._rectangle)) {
  467. res.push({
  468. x: northwestTileCoordinates.x,
  469. y: northwestTileCoordinates.y,
  470. level: imageryLevel,
  471. rectangle: _webRectangle,
  472. });
  473. }
  474. } else if (southeastTileCoordinates !== undefined) {
  475. let _webRectangle = mercatorTilingScheme.tileXYToRectangle(southeastTileCoordinates.x,
  476. southeastTileCoordinates.y,
  477. imageryLevel);
  478. if (Cesium.Rectangle.intersection(_webRectangle, this._rectangle)) {
  479. res.push({
  480. x: southeastTileCoordinates.x,
  481. y: southeastTileCoordinates.y,
  482. level: imageryLevel,
  483. rectangle: _webRectangle,
  484. });
  485. }
  486. }
  487. return res;
  488. }
  489. /**
  490. * 计算矩形的外围坐标串
  491. * @param {Cesium.Rectangle} rectangle 矩形
  492. * @return {Array<Cesium.Cartesian3>} 坐标串集合
  493. */
  494. _calculateRectangleOutlineCoordinates(rectangle) {
  495. /* 计算东南角 */
  496. let south_east = Cesium.Rectangle.southeast(rectangle);
  497. let se = Cesium.Cartographic.toCartesian(south_east);
  498. /* 计算西南角 */
  499. let south_west = Cesium.Rectangle.southwest(rectangle);
  500. let sw = Cesium.Cartographic.toCartesian(south_west);
  501. /* 计算东北角 */
  502. let north_east = Cesium.Rectangle.northeast(rectangle);
  503. let ne = Cesium.Cartographic.toCartesian(north_east);
  504. /* 计算西北角 */
  505. let north_west = Cesium.Rectangle.northwest(rectangle);
  506. let nw = Cesium.Cartographic.toCartesian(north_west);
  507. return [sw, se, ne, nw, sw];
  508. }
  509. /**
  510. * 根据Entity的名称批量删除Entity
  511. * @param {String} entityName 实体名称
  512. */
  513. _removeEntityByName(entityName) {
  514. /* 获取实体集合 */
  515. var entities = this._entities;
  516. /* 如果不存在实体集合或集合中没有数据 则返回 */
  517. if (!entities || !entities.values) return;
  518. var delEntitys = [];
  519. /* 循环获取当前集合中的所有实体 */
  520. for (var i = 0; i < entities.values.length; i++) {
  521. if (entities.values[i].name == entityName) {
  522. delEntitys.push(entities.values[i]);
  523. }
  524. }
  525. /* 删除符合条件的所有实体 */
  526. for (var i = 0; i < delEntitys.length; i++) {
  527. entities.remove(delEntitys[i]);
  528. }
  529. }
  530. }
  531. /* 对外方法 */
  532. Object.assign(CrImageServerLayer.prototype, /** @lends CrImageServerLayer.prototype */ {
  533. /**
  534. * 隐藏
  535. */
  536. hide: function() {
  537. this._console('隐藏');
  538. this._isUpdateTile = false;
  539. /* 清理资源 */
  540. this._removeEntityByName(this._renderName);
  541. /* 清理渲染 */
  542. this._renderEntities.clear();
  543. },
  544. /**
  545. * 显示
  546. */
  547. show: function() {
  548. this._console('显示');
  549. this._isUpdateTile = true;
  550. },
  551. /**
  552. * 设置透明度
  553. * @param {Number} opacity [0-1]
  554. */
  555. setOpacity: function(opacity) {
  556. if (opacity === undefined || typeof opacity !== 'number') return;
  557. if (opacity >= 1) this._opacity = 1.0;
  558. if (opacity <= 0) this._opacity = 0.0;
  559. this._opacity = parseFloat(opacity);
  560. }
  561. })
  562. /* 下载线程函数 */
  563. function downloadWorker() {
  564. /* 接收主线程发送的文件下载请求 */
  565. onmessage = function(event) {
  566. let data = event.data;
  567. /* 创建下载数据链接 */
  568. let url = data.url + '/tile/' + data.level + '/' + data.y + '/' + data.x;
  569. /* 创建下载相关 并下载 */
  570. let xhr = new XMLHttpRequest();
  571. xhr.open('get', url, true);
  572. xhr.responseType = "blob"; //设置返回类型,此处我用于下载文件 所以返回blob
  573. xhr.onload = function() {
  574. // 请求完成
  575. if (this.status === 200) {
  576. var blob = this.response;
  577. var bmpPromise = createImageBitmap(blob, {
  578. imageOrientation: "none",
  579. premultiplyAlpha: "none",
  580. colorSpaceConversion: "default",
  581. });
  582. bmpPromise.then(function(image) {
  583. let outObj = {
  584. key: data.key,
  585. x: data.x,
  586. y: data.y,
  587. level: data.level,
  588. image: image,
  589. }
  590. postMessage(outObj);
  591. })
  592. } else {
  593. console.log('===>>>', url + ' Not found');
  594. }
  595. }
  596. /* 发送请求 */
  597. xhr.send();
  598. }
  599. }
  600. /* 输出类 */
  601. export default CrImageServerLayer