最近对接某政务中心申请的地图服务,是4490的坐标系,其内部的sdk当一个宝一样催了n回也不愿意发,一直说走流程,无奈项目开发周期紧只能自己动手了。
本篇内容参考文章 Cesium 之加载ArcGIS Server 4490切片服务(含orgin -400 400
本文基于cesium 1.132.0版本调整,不同版本可能代码行数或者文件结构不同
主要分为三步
- 修改下载cesium源码
- 修改源码内对应文件
- 打包项目到本地目录中使用
一、克隆源码
js
//1.通过git下载源码
git clone https://github.com/CesiumGS/cesium.git
//2.npm install
npm install
二、修改文件
1.修改ArcGisMapServerImageryProvider.js
路径:packages\engine\Source\Scene\ArcGisMapServerImageryProvider.js
在文件夹内搜索 spatialReference.wkid === 4326 有两处需要调整的地方


js
// 1.在148行左右添加对4490坐标系的判断
else if (data.tileInfo.spatialReference.wkid === 4490) {
imageryProviderBuilder.tilingScheme = new GeographicTilingScheme({
ellipsoid : imageryProviderBuilder.ellipsoid,
});
}
//2.在206行左右增加对4490坐标系的判断
else if (data.fullExtent.spatialReference.wkid === 4326 || data.fullExtent.spatialReference.wkid === 4490) {
imageryProviderBuilder.rectangle = Rectangle.fromDegrees(
data.fullExtent.xmin,
data.fullExtent.ymin,
data.fullExtent.xmax,
data.fullExtent.ymax,
);
}
2.修改GeographicTilingScheme.js文件
路径:packages\engine\Source\Core\GeographicTilingScheme.js
有三处修改的地方,分别搜索1和2可以一起替换
- 1.GeographicTilingScheme
- 2.getNumberOfXTilesAtLevel和getNumberOfYTilesAtLevel
js
//1.在25行附近替换GeographicTilingScheme
function GeographicTilingScheme(options) {
options = options ?? Frozen.EMPTY_OBJECT;
if (defined(options.tileInfo)
&& defined(options.tileInfo.spatialReference)
&& defined(options.tileInfo.spatialReference.wkid)
&& options.tileInfo.spatialReference.wkid == 4490) {
this._tileInfo = options.tileInfo;
this._ellipsoid = options.ellipsoid ?? Ellipsoid.CGCS2000;
this._rectangle = options.rectangle ?? Rectangle.fromDegrees(-180, -90, 180, 90);
this._numberOfLevelZeroTilesX = options.numberOfLevelZeroTilesX ?? 4;
this._numberOfLevelZeroTilesY = options.numberOfLevelZeroTilesY ?? 2;
}
else {
this._ellipsoid = options.ellipsoid ?? Ellipsoid.WGS84;
this._rectangle = options.rectangle ?? Rectangle.MAX_VALUE;
this._numberOfLevelZeroTilesX = options.numberOfLevelZeroTilesX ?? 2;
this._numberOfLevelZeroTilesY = options.numberOfLevelZeroTilesY ?? 1;
}
this._projection = new GeographicProjection(this._ellipsoid);
}
js
//2.在130行附近替换掉getNumberOfXTilesAtLevel和getNumberOfYTilesAtLevel
/**
* Gets the total number of tiles in the X direction at a specified level-of-detail.
*
* @param {Number} level The level-of-detail.
* @returns {Number} The number of tiles in the X direction at the given level.
*/
GeographicTilingScheme.prototype.getNumberOfXTilesAtLevel = function (level) {
if (!defined(this._tileInfo)) {
return this._numberOfLevelZeroTilesX << level
} else { // 使用切片矩阵计算
var currentMatrix = this._tileInfo.lods.filter(function (item) {
return item.level === level
})
var currentResolution = currentMatrix[0].resolution
// return Math.round(360 / (this._tileInfo.rows * currentResolution))
return Math.round(CesiumMath.toDegrees(CesiumMath.TWO_PI * 2) / (this._tileInfo.rows * currentResolution));
}
};
/**
* Gets the total number of tiles in the Y direction at a specified level-of-detail.
*
* @param {Number} level The level-of-detail.
* @returns {Number} The number of tiles in the Y direction at the given level.
*/
GeographicTilingScheme.prototype.getNumberOfYTilesAtLevel = function (level) {
if (!defined(this._tileInfo)) {
return this._numberOfLevelZeroTilesY << level
} else { // 使用切片矩阵计算
var currentMatrix = this._tileInfo.lods.filter(function (item) {
return item.level === level
})
var currentResolution = currentMatrix[0].resolution
// return Math.round(180 / (this._tileInfo.cols * currentResolution))
return Math.round(CesiumMath.toDegrees(CesiumMath.TWO_PI * 2) / (this._tileInfo.cols * currentResolution));
}
};
3.修改Ellipsoid.js
路径:packages\engine\Source\Core\Ellipsoid.js
搜索:new Ellipsoid(6378137.0, 6378137.0, 6356752.3142451793)

js
//在235行附近将这段代码添加到WGS84的下方
Ellipsoid.CGCS2000 = Object.freeze(new Ellipsoid(6378137.0, 6378137.0, 6356752.31414035585));
到这里源码的替换部分已经全部完成,接下来就是打包进行使用
三、打包cesium
在package.json中可以看到对应的打包命令,这里直接使用build-release
js
npm run build-release

打包后的文件放在Build/Cesium文件夹内 在build目录下还有其他版本,有兴趣可以自行关注
打包的文件结构
将整体Cesium文件夹放到public目录下使用
js
//如果通过<script>标签引用
<link href="/public/Cesium/Widgets/widgets.css" rel="stylesheet">
<script type="text/javascript" src="/public/Cesium2/Cesium.js"></script>
//通过import使用
import * as Cesium from "/public/Cesium/index.js";
import "/public/Cesium/Widgets/widgets.css";
最后具体使用示例
js
// 声明Cesium Viewer实例
let viewer = null;
// 组件挂载后初始化Cesium
onMounted(async () => {
// 初始化Cesium Viewer
viewer = new Cesium.Viewer('cesiumContainer', {
// 基础配置
animation: false, // 动画小部件
baseLayerPicker: false, // 底图选择器
fullscreenButton: false, // 全屏按钮
vrButton: false, // VR按钮
geocoder: false, // 地理编码搜索框
homeButton: false, // 主页按钮
infoBox: false, // 信息框
sceneModePicker: false, // 场景模式选择器
selectionIndicator: false, // 选择指示器
timeline: false, // 时间轴
navigationHelpButton: false, // 导航帮助按钮
navigationInstructionsInitiallyVisible: false, // 导航说明初始可见性
scene3DOnly: false, // 仅3D场景
});
// 隐藏logo
viewer.cesiumWidget.creditContainer.style.display = "none";
viewer.scene.globe.enableLighting = false;
//前提先把场景上的图层全部移除或者隐藏
viewer.scene.globe.baseColor = new Cesium.Color(0.0, 0.1, 0.2, 1.0); //修改地图为暗蓝色背景
// 设置抗锯齿
viewer.scene.postProcessStages.fxaa.enabled = true;
// 清除默认底图
viewer.imageryLayers.remove(viewer.imageryLayers.get(0));
//这里使用的是开源的4326坐标系展示,替换成自己的4490坐标系就行
const esri = await Cesium.ArcGisMapServerImageryProvider.fromUrl('https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer')
viewer.imageryLayers.addImageryProvider(esri);
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK );
// 设置初始位置 长沙市上空经纬度28.2312227, 112.9334574
const boundingSphere = new Cesium.BoundingSphere(
Cesium.Cartesian3.fromDegrees(113.1334574, 28.2312227, 500),
60000
);
// 定位到初始位置
viewer.camera.flyToBoundingSphere(boundingSphere, {
// 定位到初始位置的过渡时间,设置成0,就没有过渡,类似一个过场的动画时长
duration: 0,
});
})