/* 引入Cesium */ import * as Cesium from 'cesium'; /* 引入jquery 这个必须使用 否则导致后期使用$ $.fn. 的内容全部失效*/ import $ from 'jquery'; /* 引入 */ import ArcgisImageryProvider from './ArcgisImageryProvider.js'; /* 引入自定义图层 */ import CrImageServerLayer from './CrImageServerLayer.js'; // /* 扩展更改属性 */ // Cesium.TileCoordinatesImageryProvider.prototype.requestImage = function( // x, // y, // level, // request // ) { // const canvas = document.createElement("canvas"); // canvas.width = 256; // canvas.height = 256; // const context = canvas.getContext("2d"); // const cssColor = this._color.toCssColorString(); // context.strokeStyle = cssColor; // context.lineWidth = 2; // context.strokeRect(1, 1, 255, 255); // context.font = "bold 25px Arial"; // context.textAlign = "center"; // context.fillStyle = cssColor; // context.fillText(`L: ${level}`, 124, 86); // context.fillText(`X: ${x}`, 124, 136); // context.fillText(`Y: ${y}`, 124, 186); // /* 填充图片试试 */ // let baseUrl = // 'http://218.59.194.74:6080/arcgis/rest/services/LYLSQ_GHT_102100_202112/MapServer/Tile/'; // let imageObj = new Image(); // imageObj.crossOrigin = "anonymous"; // 添加这行代码 // imageObj.width = 256; // imageObj.height = 256; // imageObj.style.opacity = 0.3; // /* 做个转换 */ // let rectangle = this._tilingScheme.tileXYToNativeRectangle(x, y, level); // // if (this.onRequestRectangle) this.onRequestRectangle(x, y, level, rectangle); // // return Promise.resolve(canvas); // return new Promise(function(resolve, reject) { // imageObj.onload = function() { // console.log('===>>>', '填充图片'); // context.fillStyle = context.createPattern(imageObj, 'no-repeat'); // context.fillRect(0, 0, 256, 256); // resolve(canvas); // // let entity = new Cesium.Entity({ // // rectangle: { // // coordinates: rectangle, // // material: Cesium.Color.RED, // // } // // }); // // resolve(entity); // } // imageObj.src = baseUrl + level + '/' + y + '/' + x; // }) // }; class CrMap { /** * 默认初始化 * @param {JSON} options 配置项 * @param {String} options.selector 加载地图的Dom空间Id * @param {String} options.sourcePath 资源目录 */ constructor(options) { let _self = this; /* 设置token 这很重要 否则将导致地图无法加载 */ Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxNzM5YjQ3MC03YmMxLTRmMjAtOTk4Yi0yNDMyMDZlOTQzYTYiLCJpZCI6NTU5MjAsImlhdCI6MTYyNDI0NTM5NX0.diydVWFzw5C5rQlHaFYkdDJoSorcdex81KpWcntyICo'; Cesium.buildModuleUrl.setBaseUrl(options.sourcePath); console.log("三维资源目录", Cesium.buildModuleUrl.getCesiumBaseUrl()); /* 设置地图容器 */ this._selector = options.selector; /* 初始化地图控件 */ this._viewer = this._initMap(); /* 注册事件 */ // this._registerEvent(); /* 初始化资源 */ this._initResource(); /* 初始化变量 地图基础图层集合*/ this._imageryLayers = this._viewer.imageryLayers; /* 初始化变量 地图原语集合 */ this._primitives = this._viewer.scene.primitives; /* 初始化变量 地图绘制实体集合 */ this._entities = this._viewer.entities; /* 初始化变量 数据源集合 */ this._dataSources = this._viewer.dataSources; //数据源集合 /* 注册事件 */ this._viewer.scene.postRender.addEventListener(sss => { }); this._viewer.camera.changed.addEventListener(function() { // console.log('===>>>', '相机变化'); }) this._viewer.camera.moveEnd.addEventListener(function(event) { // console.log('===>>>', '相机移动'); // console.log('===>>>', _self._viewer.scene.globe); // _self._drawTileGrid(); }); } _drawTileGrid() { let _self = this; let tilesToRender = _self._viewer.scene.globe._surface._tilesToRender; let renderRectangles = {}; let mercatorTilingScheme = new Cesium.WebMercatorTilingScheme(); for (let i = 0; i < tilesToRender.length; i++) { let render = tilesToRender[i]; let imageryLevel = render.level; /* 获取矩形 */ let rectangle = render._rectangle; /* 判断北西角点的墨卡托投影瓦片信息 */ let northwestTileCoordinates = mercatorTilingScheme.positionToTileXY( Cesium.Rectangle.northwest(rectangle), imageryLevel ); if (northwestTileCoordinates !== undefined) { let _webRectangle = mercatorTilingScheme.tileXYToRectangle(northwestTileCoordinates.x, northwestTileCoordinates.y, imageryLevel); let jsonIndex = '[' + northwestTileCoordinates.x + ',' + northwestTileCoordinates.y + ',' + imageryLevel + ']'; if (renderRectangles[jsonIndex] === undefined) { renderRectangles[jsonIndex] = { x: northwestTileCoordinates.x, y: northwestTileCoordinates.y, level: imageryLevel, rectangle: _webRectangle, lineColor: Cesium.Color.YELLOW, } } } /* 判断南东角点的墨卡托投影瓦片信息 */ let southeastTileCoordinates = mercatorTilingScheme.positionToTileXY( Cesium.Rectangle.southeast(rectangle), imageryLevel ); if (southeastTileCoordinates !== undefined) { let _webRectangle = mercatorTilingScheme.tileXYToRectangle(southeastTileCoordinates.x, southeastTileCoordinates.y, imageryLevel); let jsonIndex = '[' + southeastTileCoordinates.x + ',' + southeastTileCoordinates.y + ',' + imageryLevel + ']'; if (renderRectangles[jsonIndex] === undefined) { renderRectangles[jsonIndex] = { x: southeastTileCoordinates.x, y: southeastTileCoordinates.y, level: imageryLevel, rectangle: _webRectangle, lineColor: Cesium.Color.YELLOW, } } } } console.log('===>>>', renderRectangles); if (JSON.stringify(renderRectangles) !== '{}') { _self._appendRectangleFillImage(renderRectangles); } } _appendRectangle(tilesJson) { let _self = this; let entityName = 'tilesRectangle'; this._removeEntityByName(entityName); for (let tile in tilesJson) { let tileJson = tilesJson[tile]; let tileRow = tileJson.x; let tileColumn = tileJson.y; let tileLevel = tileJson.level; let entityId = tileRow + "_" + tileColumn + "_" + tileLevel; /* 查询实体是否存在 */ if (_self._entities.getById(entityId) === undefined) { let bjPositions = _self._calculateRectangleOutlineCoordinates(tileJson .rectangle); let tileEntity = new Cesium.Entity({ name: entityName, id: entityId, rectangle: { coordinates: tileJson.rectangle, material: Cesium.Color.RED.withAlpha(0.0), }, polyline: { positions: bjPositions, material: tileJson.lineColor, width: 5, clampToGround: true, //开启贴地 如果有模型则贴模型 } }); // console.log('===创建的矩形>>>', entityId); _self._entities.add(tileEntity); } } } _appendRectangleFillImage(tilesJson) { let _self = this; let entityName = 'tilesRectangle'; this._removeEntityByName(entityName); let baseUrl = 'http://218.59.194.74:6080/arcgis/rest/services/LYLSQ_GHT_102100_202112/MapServer/Tile/'; for (let tile in tilesJson) { let tileJson = tilesJson[tile]; let tileRow = tileJson.x; let tileColumn = tileJson.y; let tileLevel = tileJson.level; let entityId = tileRow + "_" + tileColumn + "_" + tileLevel; /* 查询实体是否存在 */ if (_self._entities.getById(entityId) === undefined) { let imageObj = new Image(); imageObj.crossOrigin = "anonymous"; // 添加这行代码 imageObj.width = 256; imageObj.height = 256; imageObj.style.opacity = 0.3;; imageObj.onload = function() { let material = new Cesium.ImageMaterialProperty({ image: imageObj, transparent: true, }); let bjPositions = _self._calculateRectangleOutlineCoordinates(tileJson .rectangle); let tileEntity = new Cesium.Entity({ name: entityName, id: entityId, rectangle: { coordinates: tileJson.rectangle, material: material, //Cesium.Color.RED.withAlpha(0.9), }, polyline: { positions: bjPositions, material: Cesium.Color.BLUE, // width: 2, clampToGround: true, //开启贴地 如果有模型则贴模型 } }); console.log('===创建的矩形>>>', entityId); _self._entities.add(tileEntity); } imageObj.src = baseUrl + tileLevel + '/' + tileColumn + '/' + tileRow; } } } /** * 计算矩形的外围坐标串 * @param {Cesium.Rectangle} rectangle 矩形 * @return {Array} 坐标串集合 */ _calculateRectangleOutlineCoordinates(rectangle) { /* 计算东南角 */ let south_east = Cesium.Rectangle.southeast(rectangle); let se = Cesium.Cartographic.toCartesian(south_east); /* 计算西南角 */ let south_west = Cesium.Rectangle.southwest(rectangle); let sw = Cesium.Cartographic.toCartesian(south_west); /* 计算东北角 */ let north_east = Cesium.Rectangle.northeast(rectangle); let ne = Cesium.Cartographic.toCartesian(north_east); /* 计算西北角 */ let north_west = Cesium.Rectangle.northwest(rectangle); let nw = Cesium.Cartographic.toCartesian(north_west); return [sw, se, ne, nw, sw]; } /** * 初始化地图 */ _initMap() { let viewer = new Cesium.Viewer(this._selector, { animation: false, //是否显示动画控件 baseLayerPicker: false, //地图切换控件(底图以及地形图)是否显示,默认显示true timeline: false, //是否显示时间线控件,默认true navigationHelpButton: false, //是否显示帮助信息控件 sceneModePicker: false, //是否显示3D/2D选择器 infoBox: false, //点击要素之后显示的信息,默认true clampToGround: true, //开启贴地 homeButton: false, //主页按钮,默认true geocoder: false, //地名查找,默认true scene3DOnly: true, //如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源 fullscreenButton: false, //全屏按钮,默认显示true shadows: false, //阴影 imageryProvider: new Cesium.SingleTileImageryProvider({ url: Cesium.buildModuleUrl('Assets/Images/earth_3.jpg'), }), selectionIndicator: false, //选中元素显示,默认true选中元素显示,默认true }); viewer._cesiumWidget._creditContainer.style.display = "none"; //隐藏版本信息 /* 深度检测开启/关闭 此项设置为true可以查看哪些内容掉到地下了,默认情况下为false 否则会导致绘制的点只能看见一半 */ viewer.scene.globe.depthTestAgainstTerrain = true; //地形不透明 地形检测 viewer.imageryLayers.get(0).show = true; //删除默认加载的影像,显示蓝色地球 viewer.scene.skyBox.show = false; //是否显示星空 viewer.scene.sun.show = true; //是否显示太阳 viewer.scene.moon.show = false; //是否显示有月亮 viewer.scene.skyAtmosphere.show = true; //是否隐藏大气圈 viewer.scene.globe.show = true; //是否显示地球 viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType .LEFT_DOUBLE_CLICK); //取消鼠标左键双击 viewer.scene.debugShowFramesPerSecond = true; //是否显示帧FPS viewer.scene.requestRenderMode = false; //启动主动渲染 这样地图加载完成后停止渲染 可节省CPU的开支 /* 开启精细渲染 不要太大 否则会导致效率下降 对WEB系统不太适应*/ // viewer._cesiumWidget._supportsImageRenderingPixelated = Cesium.FeatureDetection // .supportsImageRenderingPixelated(); // viewer._cesiumWidget._forceResize = true; // if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) { // var vtxf_dpr = window.devicePixelRatio; // // 适度降低分辨率 // while (vtxf_dpr >= 2.0) { // vtxf_dpr /= 2.0; // } // // alert(vtxf_dpr); // viewer.resolutionScale = 2.6; // } return viewer; } /** * 初始化资源 */ _initResource() { /* 草图工具绘制的点图片 */ this._sketchPointImage = 'data:image/png;base64,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'; } /** * 注册事件 */ _registerEvent() { let _self = this; let handler = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas); /* 挂接点击事件监听 */ handler.setInputAction(function(event) { let res = _self._getLocation(event.position); console.log('点击位置', JSON.stringify(res)); }, Cesium.ScreenSpaceEventType.LEFT_CLICK); } /** * 弧度转度 * @param {Number} arc 弧度 * @return {Number} 角度 */ _arcToDegree(arc) { return arc / Math.PI * 180; } /** * 普通颜色值转换为Cesium颜色 * @param {int} red 红色[0~255] * @param {int} green 绿色[0~255] * @param {int} blue 蓝色[0~255] * @param {int} alpha 透明度[0~1] */ _toColor(red, green, blue, alpha) { return new Cesium.Color(red / 255.0, green / 255.0, blue / 255.0, alpha); } /** * 根据Entity的名称批量删除Entity * @param {string} entityName 实体名称 */ _removeEntityByName(entityName) { /* 获取实体集合 */ var entities = this._entities; /* 如果不存在实体集合或集合中没有数据 则返回 */ if (!entities || !entities.values) return; var delEntitys = []; /* 循环获取当前集合中的所有实体 */ for (var i = 0; i < entities.values.length; i++) { if (entities.values[i].name == entityName) { delEntitys.push(entities.values[i]); } } /* 删除符合条件的所有实体 */ for (var i = 0; i < delEntitys.length; i++) { entities.remove(delEntitys[i]); } /* 更新场景 */ this.updateScene(); } /** * 获取屏幕点的经纬度及高度 如果点击位置有模型则获取模型高度 否则获取地形高度 * @param {JSON} screenPoint * @param {Number} screenPoint.x 屏幕坐标x * @param {Number} screenPoint.y 屏幕坐标y * @return {JSON} {lng:lat:height:} */ _getLocation(screenPoint) { let res = { lng: undefined, lat: undefined, height: undefined } /* 从相机位置到 windowPosition 处的像素创建射线在世界坐标系中 */ let ray = this._viewer.scene.camera.getPickRay(screenPoint); /* 找到射线与渲染的地球表面之间的交点 */ let position = this._viewer.scene.globe.pick(ray, this._viewer.scene); /* 获取地理位置的制图表达 */ let cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position); /* 查询屏幕位置的要素 */ let feature = this._viewer.scene.pick(screenPoint); if (!feature) { res.lng = this._arcToDegree(cartographic.longitude); res.lat = this._arcToDegree(cartographic.latitude); res.height = cartographic.height; } else { let cartesian = this._viewer.scene.pickPosition(screenPoint); if (Cesium.defined(cartesian)) { let cartographic = Cesium.Cartographic.fromCartesian(cartesian); res.lng = this._arcToDegree(cartographic.longitude); res.lat = this._arcToDegree(cartographic.latitude); res.height = cartographic.height; } } /* 返回结果 */ return res; } /** * 根据地形或实景或模型检测当前屏幕位置的世界坐标系位置 * @param {JSON} screenPosition 屏幕坐标 * @param {Number} screenPosition.x 屏幕坐标x * @param {Number} screenPosition.y 屏幕坐标y */ _getScreenClickPosition(screenPosition) { let resCartesian = undefined; /* 检测该位置是否存在实景或模型 */ let feature = this._viewer.scene.pick(screenPosition); if (Cesium.defined(feature)) { /* 说明检测到了实景或模型对象 */ let tempCartesian = this._viewer.scene.pickPosition(screenPosition); if (Cesium.defined(tempCartesian)) resCartesian = tempCartesian.clone(); } else { /* 未检测到模型或实景 返回地形位置 */ let ray = this._viewer.scene.camera.getPickRay(screenPosition); let tempCartesian = this._viewer.scene.globe.pick(ray, this._viewer.scene); if (Cesium.defined(tempCartesian)) resCartesian = tempCartesian.clone(); } return resCartesian; } /** * 搜索指定Id的上下关联图层索引 * @param {string} layerId 图层Id */ _searchCorrelationLayerIndex(layerId) { if (this._layerConfigs == undefined) { this._layerConfigs = []; } var index = -1; for (var i in this._layerConfigs) { if (this._layerConfigs[i].layId == layerId) { index = parseInt(i); break; } } if (index == -1) return undefined; var minIndex = -1; var maxIndex = -1; /* 找该图层底部的图层 */ for (var i = index - 1; i >= 0; i--) { minIndex = this._imageryLayers.indexOf(window[this._layerConfigs[i].layId]); if (minIndex != -1) { break; } } /* 找该图层顶部的图层 */ for (var i = index + 1; i < this._layerConfigs.length; i++) { maxIndex = this._imageryLayers.indexOf(window[this._layerConfigs[i].layId]); if (maxIndex != -1) { break; } } /* 返回寻找结果 */ return { minIndex: minIndex, maxIndex: maxIndex }; } /** * 添加provider到地图中 * @param {Object} provider 图层构建器 * @param {Object} layerId 图层Id */ _addImageryProvider(provider, layerId) { let id = layerId == undefined ? this._guid() : layerId; let resSearch = this._searchCorrelationLayerIndex(id); let resLayer = undefined; if (resSearch != undefined && resSearch.maxIndex != -1) { /* 找到该图层顶部的关联图层 则直接插入到该图层到底部 */ resLayer = this._imageryLayers.addImageryProvider(provider, resSearch.maxIndex); } else if (resSearch != undefined && resSearch.minIndex != -1 && resSearch.minIndex != this .imageryLayers.length - 1) { /* 找到该图层底部关联的图层 且该图层不是最顶部的图层 则将该图层加载到这个图层之上 */ resLayer = this._imageryLayers.addImageryProvider(provider, resSearch.minIndex + 1); } else { resLayer = this._imageryLayers.addImageryProvider(provider); } /* 加入到整体图层中 以便可以删除对应的图层 */ window[id] = resLayer; /* 返回该图层 */ return resLayer; } /** * 创建GUID */ _guid() { function S4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); } return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()); } /** * 三维模型旋转平移 * @param {Object} tileset 三维模型数据 * @param {JSON} params 参数配置项 * @param {JSON} params.tx x方向平移 * @param {JSON} params.ty y方向平移 * @param {JSON} params.tz z方向平移 * @param {JSON} params.rx x方向旋转 * @param {JSON} params.ry y方向旋转 * @param {JSON} params.rz z方向旋转 */ _update3dtilesMaxtrix(tileset, params) { //旋转 var mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(params.rx)); var my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(params.ry)); var mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(params.rz)); var rotationX = Cesium.Matrix4.fromRotationTranslation(mx); var rotationY = Cesium.Matrix4.fromRotationTranslation(my); var rotationZ = Cesium.Matrix4.fromRotationTranslation(mz); //平移 var position = Cesium.Cartesian3.fromDegrees(params.tx, params.ty, params.tz); var m = Cesium.Transforms.eastNorthUpToFixedFrame(position); //旋转、平移矩阵相乘 Cesium.Matrix4.multiply(m, rotationX, m); Cesium.Matrix4.multiply(m, rotationY, m); Cesium.Matrix4.multiply(m, rotationZ, m); //赋值给tileset tileset._root.transform = m; } } /** * 工具扩展 */ Object.assign(CrMap.prototype, { /** * 异步飞行 * @param {JSON} options 配置项 * @param {Object} options.target 飞行目的地目标 * @param {Int} options.duration 飞行持续时间 秒 * @param {Float} options.radians 旋转角度 度 * @param {Boolean} options.isRemove 执行完成后是否删除目标 true/false */ asyncFlyTo: function(options) { var _self = this; return new Promise((resolve, reject) => { /* 飞行 */ var flyPromise = _self._viewer.flyTo(options.target, { duration: options.duration, //飞行持续时间 offset: new Cesium.HeadingPitchRange(0.0, Cesium.Math.toRadians(options .radians)), }); /* 飞行完成 */ flyPromise.then(function(isFly) { if (isFly && options.isRemove && options.target != undefined) { _self._viewer.entities.remove(options.target); } resolve(true); }) }); }, /** * 飞向矩形区域 * @param {JSON} options 配置项 * @param {Float} options.strLng 矩形起始点经度 * @param {Float} options.strLat 矩形起始点纬度 * @param {Float} options.endLng 矩形终止点经度 * @param {Float} options.endLat 矩形终止点纬度 */ flyToRectangle: function(options) { var _self = this; this._entities.removeById('flyRectangle'); var extent = Cesium.Rectangle.fromDegrees(options.strLng, options.strLat, options.endLng, options.endLat); /* 创建飞行矩形 */ var flyRectangle = this._entities.add({ id: 'flyRectangle', name: 'flyRectangle', rectangle: { coordinates: extent, material: Cesium.Color.GREEN.withAlpha(0.0), height: 200.0, outline: false } }); this.asyncFlyTo({ target: flyRectangle, //定位对象 isRemove: false, //定位完成后是否删除 duration: 3, radians: -90, }).then(function(isFly) { if (isFly) { _self.asyncFlyTo({ target: flyRectangle, //定位对象 isRemove: true, //定位完成后是否删除 duration: 1, radians: -40, }).then(function(isFly) { if (isFly && options.success != undefined) { options.success(); } }) } }).catch(function(err) { alert(err); }) }, /** * 设置显示范围 * @param {JSON} options 配置项 * @param {Float} options.lng 经度 * @param {Float} options.lat 纬度 * @param {Float} options.alt 高度 * @param {Float} options.heading 指北角度 度 * @param {Float} options.pitch 垂直视角 度 * @param {Float} options.roll 翻滚视角 度 */ setMapRange: function(options) { this._viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(options.lng, options.lat, options.alt), orientation: { //此视角为观察者/相机 heading: options.heading, pitch: Cesium.Math.toRadians(options.pitch), roll: options.roll } }); }, /** * 刷新场景 刷新一帧 */ updateScene: function() { this._viewer.scene.requestRender(); }, /** * 调用相机方法飞到指定位置 * @param {Object} options 配置项 * @param {Number} options.lng 相机位置经度 度格式 * @param {Number} options.lat 相机位置纬度 度格式 * @param {Number} options.alt 相机位置高度 度格式 * @param {Number} options.heading 方向角度 度格式 * @param {Number} options.picth 俯仰角度 度格式 * @param {Number} options.roll 滚动角度 度格式 */ cameraFlyToo: function(options) { this._viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(options.lng, options.lat, options.alt), orientation: { heading: Cesium.Math.toRadians(options.heading, 0), pitch: Cesium.Math.toRadians(options.pitch), roll: Cesium.Math.toRadians(options.roll), }, duration: 3, }) }, /** * 获取相机视图参数 * @return {JSON} 相机视角参数{lng:lat:alt:heading:pitch:roll} */ getCameraViewParams: function() { var _self = this; /* 获取相机位置 并转换为g84格式 */ var g84Position = Cesium.Ellipsoid.WGS84.cartesianToCartographic(this._viewer.camera.position); var result = { lng: Cesium.Math.toDegrees(g84Position.longitude), lat: Cesium.Math.toDegrees(g84Position.latitude), alt: g84Position.height, pitch: Cesium.Math.toDegrees(_self._viewer.camera.pitch), heading: Cesium.Math.toDegrees(_self._viewer.camera.heading), roll: Cesium.Math.toDegrees(_self._viewer.camera.roll), } return result; }, /** * 获取视图 */ getViewer: function() { return this._viewer; } }); /** * ArcGIS扩展相关 */ Object.assign(CrMap.prototype, { /** * 查询ArcGIS服务图层的范围 * @param {String} url 图层服务地址 * @param {Int} index 图层索引Id * @param {Function} callSuccess 成功回调 * @param {Function} callError */ _queryAGServerExtent: function(url, index, callSuccess, callError) { $.ajax({ async: true, type: 'POST', dataType: 'json', url: url + '/' + index + '?f=pjson', success: function(data) { if (callSuccess != undefined) { callSuccess({ xmin: data.extent.xmin, ymin: data.extent.ymin, xmax: data.extent.xmax, ymax: data.extent.ymax, }); } }, error: function(XMLHttpRequest, textStatus, errorThrown) { if (callError != undefined) { callError(textStatus); } } }); }, /** * 查询ArcGIS服务图层的范围 * @param {String} url 图层服务地址 * @param {Int} index 图层索引Id * @param {Function} callSuccess 成功回调 * @param {Function} callError */ queryAGServerExtent: function(url, index, callSuccess, callError) { this._queryAGServerExtent(url, index, callSuccess, callError) } }) /** * 图层管理扩展 */ Object.assign(CrMap.prototype, { /** * 根据图层配置信息显示图层 * @param {JSON} options 配置项 * @param {JSON} options.config 图层配置信息 */ _showLayer(options) { console.log('当前加载的图层类型', options.layType); if (options.layType == CrMap.LayerType.mapboxLayer) { this.addMapboxLayer(options.config); } else if (options.layType == CrMap.LayerType.wmtsLayer) { this.addWmtsTileLayer(options.config); } else if (options.layType == CrMap.LayerType.imageLayer) { this.addDynamicFeatureLayerFromServer(options.config); } else if (options.layType == CrMap.LayerType.tilesetsLayer) { this.add3DTilesets(options.config); } else if (options.layType == CrMap.LayerType.agsVectorLayer) { this.addAGSVectorLayer(options.config); } else if (options.layType === CrMap.LayerType.templateLayer) { this.addUrlTemplateImageryLayer(options.config); } else if (options.layType === CrMap.LayerType.floatLayer) { this.addFloatLayer(options.config); } }, /** * 设置地形 * @param {JSON} options 配置项 * options.url{string}:地形服务URL地址 */ setTerrain(options) { var terrainLayer = new Cesium.CesiumTerrainProvider({ url: options.url, //dem的url地址 requestVertexNormals: true, // 请求照明 requestWaterMask: true // 请求水波纹效果 }); this._viewer.terrainProvider = terrainLayer; }, /** * 添加图层到图层集合中 * @param {JSON} options 配置项 * @param {String} options.layId 图层Id,唯一标识 * @param {String} options.layName 图层名称 * @param {Enum} options.layType 图层类型 * @param {Boolean} options.isShow 图层是否显示 * @param {JSON} options.config 图层配置信息,不同类型图层配置信息不一致 * @param {Function} callSuccess 成功回调 * @param {Function} callError 错误回调 */ addLayer(options, callSuccess, callError) { /* 判断用于存储图层的数组是否已经初始化,如未初始化,则进行初始化操作 */ if (!this.allLayers) this.allLayers = []; if (!options.config) { /* 如果图层没有添加配置信息 则追加 */ options.config = { id: options.layId, } } else { /* 如果已经配置了config信息,则增加id字段 */ options.config.id = options.layId; } this.allLayers.push(options); }, /** * 初始化显示 */ showInit() { for (let layConfig of this.allLayers) { if (!layConfig.isShow || layConfig.isShow == false) continue; this._showLayer(layConfig); } }, /** * 添加Mapbox图层 * @param {JSON} options 配置项 * options.id{String}:可选参数 图层Id * options.isShow{boolean}[true/false]:是否显示 */ addMapboxLayer(options) { // var mapboxProvider = new Cesium.MapboxStyleImageryProvider({ // url: 'https://api.mapbox.com/styles/v1', // username: 'chenchen1990', // styleId: 'ckvgc14xrh7mo14qowdw4wrkf', // accessToken: 'pk.eyJ1IjoiY2hlbmNoZW4xOTkwIiwiYSI6ImNrbzA3eTY1OTA3dXkyd20zdG40ZGdmNXYifQ.xWKxjBG6mEDh55_oln0nAg', // scaleFactor: true // }); let provider = new ArcgisImageryProvider({ url: 'https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer', }, 'WGS84') /* 加入图层 */ this._addImageryProvider(provider, options.id); }, /** * 添加实景数据图层 * @param {JSON} options 配置项 * @param {Array} options.url [id1,id2...]资源的Url数组 * @param {String} options.id 图层Id * @param {JSON} options.params 参数配置项,可选参数 * @param {JSON} options.params.tx x方向平移 * @param {JSON} options.params.ty y方向平移 * @param {JSON} options.params.tz z方向平移 * @param {JSON} options.params.rx x方向旋转 * @param {JSON} options.params.ry y方向旋转 * @param {JSON} options.params.rz z方向旋转 */ add3DTilesets: function(options) { let _self = this; let subLayerIds = []; let tilesets = new Cesium.PrimitiveCollection(); for (let url of options.url) { let tileLayer = new Cesium.Cesium3DTileset({ url: url, maximumScreenSpaceError: 64, // maxmumMemoryUsage: 218, // skipScreenSpaceErrorFactor: 16, // dynamicScreenSpaceError: true, // skipLevels: 1, // cullWithChildrenBounds: true, // cullRequestsWhileMoving: true, // cullRequestsWhileMovingMultiplier: 10, // 值越小能够更快的剔除 skipLevelOfDetail: true, maximumScreenSpaceError: 16, visualError: 60, //可视误差 }); let tileset = tilesets.add(tileLayer); tileset.readyPromise.then(function(primitive) { if (options.params != undefined) { _self._update3dtilesMaxtrix(primitive, options.params); } if (options && options.offsetHeight) { /* 提升高度试试 */ let boundingSphere = tileset.boundingSphere; let cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center); let surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic .latitude, 0.0); let offseth = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic .latitude, options.offsetHeight); //修改模型高度 let translation = Cesium.Cartesian3.subtract(offseth, surface, new Cesium .Cartesian3()); tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation); } }) } /* 加入图层 */ _self._primitives.add(tilesets); /* 加入公共资源 */ window[options.id] = tilesets; }, /** * 加载Wmts服务数据 * @param {JSON} options 配置项 * @param {String} options.url wmts服务地址 * @param {Number} options.maxLevel 最大缩放层级,默认19 * @param {Number} options.minLevel 最小缩放层级,默认0 * @param {Number} options.alpha[0.0-1.0]:透明度 */ addWmtsTileLayer(options) { /* 初始化图层 */ var wmtsProvider = new Cesium.WebMapTileServiceImageryProvider({ url: options.url, layer: 1, style: 'default', format: 'image/png', tileMatrixSetID: 'default028mm', maximumLevel: options.maxLevel ? options.maxLevel : 19, minimumLevel: options.minLevel ? options.maxLevel : 0, }); /* 添加图层 */ var wmtslayer = this._addImageryProvider(wmtsProvider, options.id); /* 设置透明度 */ wmtslayer.alpha = options.alpha == undefined ? 1.0 : parseFloat(options.alpha); }, /** * 加载Tms服务数据 * @param {Object} options 配置项 */ addUrlTemplateImageryLayer: function(options, callSuccess) { console.log('模版地图参数', JSON.stringify(options)); /* 判断需要的参数是否已经定义 */ if (!Cesium.defined(options) || !Cesium.defined(options.url)) { throw new DeveloperError("options.url 参数异常!"); } if (!Cesium.defined(options) || !Cesium.defined(options.maximumLevel)) { throw new DeveloperError("options.maximumLevel 参数异常!"); } var imageryProvider = new Cesium.UrlTemplateImageryProvider({ url: options.url, tilingScheme: new Cesium.WebMercatorTilingScheme(), minimumLevel: Cesium.defaultValue(options.minimumLevel, 0), maximumLevel: options.maximumLevel, }) /* 加入图层 */ let tmsLayer = this._addImageryProvider(imageryProvider); if (callSuccess) callSuccess(serviceId); }, /** * 添加浮动图层 悬浮于实景三维之上 * @param {Object} options * @param {Object} callSuccess */ addFloatLayer(options, callSuccess) { let layer = new CrImageServerLayer({ viewer: this._viewer, url: options.url, opacity: options.opacity, show: true, }); window[options.id] = layer; } }) /** * 坐标转换相关 */ Object.assign(CrMap.prototype, { /** * 地图坐标转三维坐标 * @param {JSON} geo 地理坐标 * @param {Number} geo.lng 经度 * @param {Number} geo.lat 纬度 * @param {Number} geo.height 高度 */ _GeoToCartesian(geo) { try { let cartesian = Cesium.Cartesian3.fromDegrees(geo.lng, geo.lat, geo.height); return cartesian; } catch (e) { console.log('错误', e); return undefined; } }, }); /* 扩展全局方法 */ /* 图层类型 */ CrMap.LayerType = Object.freeze({ mapboxLayer: 'mapboxLayer', //Mapbox图层 暗夜版地图 wmtsLayer: 'wmtsLayer', //wmts图层 agsVectorLayer: 'agsVectorLayer', //ArcGIS矢量服务图层 tilesetsLayer: 'tilesetsLayer', //3D Tile图层 glbsLayer: 'glbsLayer', //glb图层 geoJsonLayer: 'geoJsonLayer', //geoJson 类型图层 imageLayer: 'imageLayer', //叠加三维的图片图层 templateLayer: 'templateLayer', //模版类型图层 floatLayer: 'floatLayer', //浮动图层 }) /* 输出 */ export { CrMap }