官网:https://cesium.com/cesiumjs/
官方API文档:https://cesium.com/docs/cesiumjs-ref-doc/
官方例子:https://sandcastle.cesium.com/
var cesiumDivId = "cesiumContainer";
var online = false;
var cesiumViewer; // 后面会频繁使用
// 设置 token
Cesium.Ion.defaultAccessToken = "设置token值";
// 设置viewer参数 https://cesiumjs.org/Cesium/Build/Documentation/Viewer.html
var options = {
geocoder: false,
fullscreenButton: true,
baseLayerPicker: false,
navigationHelpButton: false
};
// 判断使用在线地图?还是离线地图?
if(online){// 在线地图
cesiumViewer = new Cesium.Viewer(cesiumDivId, options);
}else{// 离线地图
options.imageryProvider
= new Cesium.createTileMapServiceImageryProvider({
url : "http://localhost:8080/NaturalEarthII/",
flipXY: true
});
cesiumViewer = new Cesium.Viewer(cesiumDivId, options);
}
设置
Viewer
的imageryProvider
参数注意替换
天地图的tk
文档说明:
- https://cesium.com/docs/cesiumjs-ref-doc/WebMapTileServiceImageryProvider.html?classFilter=WebMapTileServiceImageryProvider
- http://lbs.tianditu.gov.cn/server/MapService.html
options.imageryProvider = new Cesium.WebMapTileServiceImageryProvider({
url: "http://t1.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=天地图的tk",
layer: "tdtBasicLayer",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "GoogleMapsCompatible",
subdomains: ['t0', "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
maximumLevel: 18,
show: false
})
设置
Viewer
的imageryProvider
参数文档说明:https://cesium.com/docs/cesiumjs-ref-doc/UrlTemplateImageryProvider.html?classFilter=UrlTemplateImageryProvider
options.imageryProvider = new Cesium.UrlTemplateImageryProvider({
url:'http://mt3.google.cn/vt/lyrs=s@110&hl=zh-CN&gl=cn&src=app&x={x}&y={y}&z={z}',
tilingScheme:new Cesium.WebMercatorTilingScheme(),
// minimumLevel:1,
maximumLevel:20,
subdomains:["mt1","mt2","mt3"],
})
设置
Viewer
的imageryProvider
参数文档说明:https://cesium.com/docs/cesiumjs-ref-doc/ArcGisMapServerImageryProvider.html
options.imageryProvider = new Cesium.ArcGisMapServerImageryProvider({
url : 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
});
// 去除版权信息
cesiumViewer._cesiumWidget._creditContainer.style.display = "none";
// 显示FPS
cesiumViewer.scene.debugShowFramesPerSecond = true;
/**
* 飞跃到指定位置
* @param scene 场景对象 e.g. Ceisum#Viewer#scene
* @param location 定位信息 e.g. {lon, lat, height}
* */
function flyToLocation(scene, location) {
scene.camera.flyTo({
destination: Cesium.Cartesian3
.fromDegrees(location.lon, location.lat, location.height)
});
};
/**
* 重置home按钮
* @param viewer 视图对象 e.g. Ceisum#Viewer
* @param location 定位信息 e.g. {lon, lat, height}
* */
function resetHomeButton(viewer, location) {
viewer.homeButton.viewModel.command.beforeExecute.addEventListener(
function (e) {
e.cancel = true;
// 飞跃到指定位置
flyToLocation(viewer.scene, location);
}
);
}
cesium-navigation
github:https://github.com/alberto-acevedo/cesium-navigation/tree/master
引入外部JS的方式
安装 nodejs
官网:https://nodejs.org/en/download/
cd 到项目根目录
运行命令:npm install
和 node build.js
编译完成后,\dist\standalone
拷贝 viewerCesiumNavigationMixin.js
页面引用 viewerCesiumNavigationMixin.js
/**
* defaultResetView:导航控件-重置按钮的默认位置
* (支持Cesium.Rectangle.fromDegrees 和 Cesium.Cartographic.fromDegrees)
* enableCompass:启用或禁用罗盘
* enableCompassOuterRing:启用或禁用指南针外环
* enableDistanceLegend:启用或禁用距离图例
* enableZoomControls:启用或禁用缩放控件
*/
var options = {
"defaultResetView": Cesium.Cartographic
.fromDegrees(116.403694, 39.914271, 10000000.0),
"enableCompass": true,
"enableCompassOuterRing": true,
"enableDistanceLegend": true,
"enableZoomControls": false
}
cesiumViewer.extend(Cesium.viewerCesiumNavigationMixin, options);
cesium-drawhelper
https://github.com/leation/drawhelper-with-cesium-v1.41
使用:
DrawHelper.js
和 DrawHelper.css
<div id="toolbar-drawhelper">div>
var drawHelper = new DrawHelper(cesiumViewer);
// buttons 属性正常是需要设置全部值的,这里是修改过 drawhelper 项目源码的
var drawToolbar = drawHelper.addToolbar(document.getElementById("toolbar-drawhelper"), {buttons: ['extent']});
// 画图监听
drawToolbar.addListener('extentCreated', function(event) {
// 构建 polygon
var extentPrimitive = new DrawHelper.ExtentPrimitive({
extent: event.extent,
material: Cesium.Material.fromType(Cesium.Material.StripeType)
});
// TODO 添加到 cesium
// 设置编辑状态
extentPrimitive.setEditable();
// 编辑监听
extentPrimitive.addListener('onEdited', function(event) {
// TODO 编辑后的逻辑
});
});
drawhelper
项目源码的修改记录:DrawHelper.js 初始化时,设置 buttons
属性,添加了是否需要配置某个按钮的判断,主要是应对不需要全部按钮初始化的场景,例如:
修改:DrawHelper.js
// 这里 if 判断,在其它按钮上,也需要配置
if(options.buttons.indexOf("marker")!=-1){
addIcon('marker', options.markerIcon, 'Click to start drawing a 2D marker', function () {
drawHelper.startDrawingMarker({
callback: function (position) {
_self.executeListeners({ name: 'markerCreated', position: position });
}
});
})
}
由于鼠标滑动时,经常滑动到提示窗口,导致有卡顿的感觉(画图不流畅),这个问题需要在 DrawHelper.css
中添加一个 css 样式进行解决 ,设置元素不会触发鼠标事件
修改:DrawHelper.css
.twipsy {
// ... 省略内容
pointer-events:none;
}
按钮图片 404 的问题,使用本文第三部分的,获取当前JS路径的方法
修改:DrawHelper.js
// 配置图片路径
var drawroot = getScriptPathByName("DrawHelper", true);
使用 Extent 画图时,除了返回 extent 数据外,还要返回 左上角 和 右下角 的点坐标
修改:DrawHelper.js
// 画图监听返回(Extent)
DrawHelper.ExtentPrimitive.prototype.setEditable = function () {
// ... 省略内容
dragHandlers: {
onDrag: function (index, position) {
// ... 省略内容
//左上角
value.firstpoint
= ellipsoid.cartesianToCartographic(corner);
// 右下角
value.secondpoint
= ellipsoid.cartesianToCartographic(position);
extent.setExtent(value);
// ... 省略内容
}
}
// ... 省略内容
}
// 编辑图形监听的返回(Extent)
_.prototype.startDrawingExtent = function (options) {
// ... 省略内容
// Now wait for start
mouseHandler.setInputAction(function (movement) {
if (movement.position != null) {
var cartesian
= scene.camera.pickEllipsoid(movement.position, ellipsoid);
if (cartesian) {
if (extent == null) {
// ... 省略内容
} else {
_self.stopDrawing();
if (typeof options.callback == 'function') {
var secondPoint
= ellipsoid.cartesianToCartographic(cartesian);
var value = getExtent(firstPoint, secondPoint);
// 左上角
value.firstpoint = firstPoint;
// 右下角
value.secondpoint = secondPoint;
options.callback(value);
}
}
}
}
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
// ... 省略内容
}
报错后,被注释的代码
修改:DrawHelper.js
// 注释了 if 判断
// disable edit if pickedobject is different or not an object
//if (!(pickedObject && !pickedObject.isDestroyed() && pickedObject.primitive)) {
extent.setEditMode(false);
//}
/**
* 使用cesium api计算两点之间的距离
* @param slon 开始经度
* @param slat 开始纬度
* @param elon 结束经度
* @param elat 结束纬度
* */
function distanceBetweenTwoPoint(slon, slat, elon, elat){
var sCartographic = Cesium.Cartographic.fromDegrees(slon, slat);
var eCartographic = Cesium.Cartographic.fromDegrees(elon, elat);
var geodesic = new Cesium.EllipsoidGeodesic();
geodesic.setEndPoints(sCartographic, eCartographic);
return geodesic.surfaceDistance;
}
/**
* 创建等高点
* @param datas 数据列表
* .e.g: [{"lon": 112, "lat": 22}, {"lon": 113, "lat": 23}]
* @param color 颜色 .e.g: Cesium.Color.RED
* @param height 高度
* */
function createContourPoiGeometry(datas, color, height){
var poiCollection = new Cesium.PointPrimitiveCollection();
for(var i=0; i<datas.length; i++){
poiCollection.add({
position: Cesium.Cartesian3
.fromDegrees(datas[i].lon, datas[i].lat, height),
color: color
});
}
return poiCollection;
};
/**
* 添加指定的几何图形
* @param primitive 几何图形集合 .e.g: Cesium.PointPrimitiveCollection()
* */
function addGeometry(primitive) {
cesiumViewer.scene.primitives.add(primitive);
}
var primitive = createContourPoiGeometry(datas, color, height);
addGeometry(primitive);
/**
* 创建 BoxGeometry
* @param length 长度
* @param width 宽度
* @param height 高度
* */
function createGeometry(length, width, height){
return Cesium.BoxGeometry.fromDimensions({
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
dimensions : new Cesium.Cartesian3(length, width, height)
});
};
/**
* 创建 PolygonGeometry
* @param extent 范围数组
* .e.g: [-120.0, 45.0, -80.0, 45.0, -80.0, 55.0, -120.0, 55.0]
* @param height geometry高度
* @param groundHeight geometry距离地面的高度
* */
function createPolygon(extent, height, groundHeight){
return new Cesium.PolygonGeometry({
polygonHierarchy: {
positions: Cesium.Cartesian3.fromDegreesArray(extent)
},
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
extrudedHeight: height,
height: groundHeight
});
};
/**
* 创建geometryInstance
* @param lon 经度
* @param lat 纬度
* @param groundHeight 距离地面高度
* @param geometry
* @param color 颜色
* @param instanceId geometryInstance的ID
* */
function createGeometryInstance(lon, lat, groundHeight, geometry, color, instanceId){
var modelMatrix;
if(lon == null || lat == null || groundHeight == null){
modelMatrix = undefined;
}else{
var scale = 5000 * 0.3;
var position
= Cesium.Cartesian3.fromDegrees(lon, lat);
var point3d
= new Cesium.Cartesian3(0.0, 0.0, groundHeight);
var translation
= Cesium.Transforms.eastNorthUpToFixedFrame(position);
var matrix
= Cesium.Matrix4.multiplyByTranslation(translation, point3d, new Cesium.Matrix4());
var modelMatrix
= Cesium.Matrix4.multiplyByUniformScale(matrix, scale, new Cesium.Matrix4());
}
// 创建 GeometryInstance
var geoInstance = new Cesium.GeometryInstance({
id: instanceId,
geometry: geometry,
modelMatrix: modelMatrix,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(color),
show: new Cesium.ShowGeometryInstanceAttribute(true)
}
});
return geoInstance;
}
/**
* 使用GeometryInstances创建Primitive
* @param instances geometryInstalce集合或单个geometryInstance
* */
function createPrimitiveWithInstances(instances){
return new Cesium.Primitive({
geometryInstances : instances,
appearance : new Cesium.PerInstanceColorAppearance({
translucent : true,
closed : true
})
});
}
/**
* 添加指定的几何图形
* @param primitive 几何图形集合 .e.g: Cesium.PointPrimitiveCollection()
* */
function addGeometry(primitive) {
cesiumViewer.scene.primitives.add(primitive);
}
// color
var color = Cesium.Color.RED.withAlpha(0.5);
// boxGeometry
var boxGeometry = createGeometry(length, width, height);
var boxGeoInstance = createGeometryInstance(lon, lat, groundHeight
, boxGeometry, color, instanceId);
var primitive = createPrimitiveWithInstances(boxGeoInstance);
addGeometry(primitive);
// polygonGeometry
var polygonGeometry = createPolygon(extent, height, groundHeight);
var polygonGeoInstance = createGeometryInstance(null, null, null
, polygonGeometry, color, instanceId);
var primitive = createPrimitiveWithInstances(polygonGeoInstance);
addGeometry(primitive);
// 保存 primitive
var polygonGeometry = createPolygon(extent, height, groundHeight);
var polygonGeoInstance = createGeometryInstance(null, null, null
, polygonGeometry, color, instanceId);
var primitive = createPrimitiveWithInstances(polygonGeoInstance);
// 动态设置 primitive
// 创建 GeometryInstance 时,需要设置ID,并且 attributes 添加 show 属性
var attributes = primitive.getGeometryInstanceAttributes(instanceId);
// 隐藏
attributes.show = Cesium.ShowGeometryInstanceAttribute.toValue(false);
// 显示
attributes.show = Cesium.ShowGeometryInstanceAttribute.toValue(true);
// 隐藏
cesiumViewer.scene.primitives.get(batchNum).getGeometryInstanceAttributes(instanceId).show = Cesium.ShowGeometryInstanceAttribute.toValue(false);
范围控件与数据模型绑定:https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/?src=Clustering.html
/**
* 追踪数据模型,并且绑定数据到范围控件
* @param model 数据模型 e.g. : {x: x, y: y}
* @param widgetId 控件ID
* */
function setCutToolTrackAndBind(model, widgetId) {
Cesium.knockout.track(model);
var toolbarWidget = document.getElementById(widgetId);
Cesium.knockout.applyBindings(model, toolbarWidget);
};
/**
* 订阅数据模型中的某个字段,用于监控数据变化和触发响应
* @param model 数据模型,e.g. : {x: x, y: y}
* @param name 模型中的字段
* @param callback 回调函数
* */
function subscribeParameter(model, name, callback) {
Cesium.knockout.getObservable(model, name).subscribe(
function (newValue) {
callback(name, newValue);
}
);
};
Uncaught Error: You cannot apply bindings multiple times to the same element.
/**
* 取消范围控件数据绑定
* @param widgetId 控件ID
* */
function setCutToolUnbind(widgetId) {
var toolbarWidget = document.getElementById(widgetId);
Cesium.knockout.cleanNode(toolbarWidget);
};
支持的事件: https://cesium.com/docs/cesiumjs-ref-doc/ScreenSpaceEventType.html?classFilter=ScreenSpaceEventType
// 监听点击事件
var handle = new Cesium.ScreenSpaceEventHandler(cesiumViewer.scene.canvas)
handle.setInputAction((event)=>{
var pick = this.viewer.scene.pick(event.position);
// 判断是否选中对象
if(pick && pick.id){
console.log("pick.id",pick.id)
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
/**
* 根据js文件名,获取页面script标签的地址
* @param jsFileName js文件名
* @param isDir true=返回当前目录路径,false=返回完整路径
* */
function getScriptPathByName(jsFileName, isDir) {
var allJsNames = document.scripts;
var path = "";
// 循环判断列表是否存在JS文件
for(var i=0; i<allJsNames.length; i++){
var tPath = allJsNames[i].src;
if(tPath.lastIndexOf(jsFileName) != -1){
path = tPath;
break;
}
};
// 判断是否获取完整路径,还是文件夹路径
if(isDir){
var tIdex = path.lastIndexOf(jsFileName);
return path.substring(0, tIdex);
}else{
return path;
}
}
// 调用
getScriptPathByName('当前js文件名', true);
/**
* 获取数据
* @param url 数据链接
* @param params 参数 e.g. {“x”: x, “y”: y}
* @param callback 回调函数
* */
function getDataToJSON(url, params, callback) {
$.ajax({
url: url,
type: "GET",
async: true,
data: params,
datatype: "json",
success: function (data) {
// console.log(data);
callback(data);
}
});
};
参考:https://segmentfault.com/a/1190000015843072
Person.js
function Person(name, age){
this.name = name;
this.age = age;
};
Person.prototype = {
// 构造函数
constructor: Person,
// 属性-国籍
nationality: "China",
// 属性-PC
pc: null,
// 测试函数
testFun: function () {
console.log("name="+this.name+" ; age="+this.age+" ; no this.name="+name
+" ; nationality="+this.nationality);
},
// 改变属性值函数
changePrototype: function () {
this.name = "zcheng";
this.age = "12";
this.nationality = "zzzzzZ";
},
// 测试初始化函数
testInit: function (num) {
console.log("num="+num);
this.pc = new PC("007", "aka-007");
}
};
PC.js
function PC(num, name) {
this.num = num;
this.name = name;
};
PC.prototype = {
cpu: "i7-4444",
getCPU: function () {
console.log("CPU=" + this.cpu);
},
getInfo: function () {
console.log("num=" + this.num + " ;name=" + this.name);
}
};
test.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Testtitle>
<script type="text/javascript" src="/scalar/Person.js">script>
<script type="text/javascript" src="/scalar/PC.js">script>
head>
<body>
body>
<script>
var p = new Person("test", "123");
p.changePrototype();
p.testFun();
p.testInit(123123123);
console.log(p.nationality);
p.pc.getCPU();
p.pc.getInfo();
script>
html>
https://github.com/oeo4b/kriging.js
/**
* 创建 N*N 的点阵,并进行插值计算
* @param points 点值数据; e.g. [{{"lon":112.19,"lat":23.99,"val":10}}]
* @param matrixNum 点阵长宽数量
*/
function createDotMatrix(points, matrixNum){
// 将数据分离
var lons = [];
var lats = [];
var vals = [];
for(var i=0; i<points.length; i++){
lons[i] = points[i]["lon"];
lats[i] = points[i]["lat"];
vals[i] = points[i]["val"];
}
// 计算经纬度最大值和最小值
var maxLon = lons.max();
var minLon = lons.min();
var maxLat = lats.max();
var minLat = lats.min();
// 根据点阵长宽数量,切分经纬度
var distLon = (maxLon - minLon) / matrixNum;
var distLat = (maxLat - minLat) / matrixNum;
// 循环计算点位置和插值计算
var tempLon = minLon;
for(var i=0; i<matrixNum; i++){
// 插值经度
tempLon = tempLon + distLon;
var tempLat = minLat;
for(var j=0; j<matrixNum; j++){
// 插值纬度
tempLat = tempLat + distLat;
var kval = getKrigingPredict(vals, lons, lats, tempLon, tempLat);
console.log(tempLon+","+tempLat+","+kval);
}
}
}
/**
* 使用kriging算法,进行值的预测
* @param allValue 已知经纬度对应的值
* @param allLon 已知数据的所有经度
* @param allLat 已知数据的所有纬度
* @param predictLon 需要预测值的经度
* @param predictLat 需要预测值的纬度
*/
function getKrigingPredict(allValue, allLon, allLat, predictLon, predictLat){
var model = "exponential";
var sigma2 = 0;
var alpha = 100;
var variogram = kriging.train(allValue, allLon, allLat, model, sigma2, alpha);
return kriging.predict(predictLon, predictLat, variogram);
};
//点数据
var points = [{"lon":116.195,"lat":39.997011,"val":10}
,{"lon":116.325218,"lat":39.949238,"val":50}
,{"lon":116.215122,"lat":39.983081,"val":150}
,{"lon":116.25709,"lat":39.983965,"val":86}
,{"lon":116.314294,"lat":39.990378,"val":200}];
var matrixNum = 30; //点阵长宽数量
createDotMatrix(points, matrixNum);
Array.prototype.max = function() {
return Math.max.apply(null, this);
};
Array.prototype.min = function() {
return Math.min.apply(null, this);
};