博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Cesium几个案例介绍
阅读量:5268 次
发布时间:2019-06-14

本文共 8169 字,大约阅读时间需要 27 分钟。

前言

本文为大家介绍几个Cesium的Demo,通过这几个Demo能够对如何使用Cesium有进一步的了解,并能充分理解Cesium的强大之处和新功能。其他的无需多言,如果还不太了解什么是Cesium,可以参见我的另外两篇关于Cesium的博客,下面直接进入正题。

一、 监听HTML控件

在Cesium中可以很方便的监听前台HTML控件,类似C#等语言中的MVVM。

1.1 前台控件

前台控件效果如下:

704456-20171220151510787-1509732536.png

代码如下:

SRTM
SLOPE
Type

首先创建一个div,js监测此div中的控件,重要的是id。

在此div中创建input,一个或多个input对应js中的一个变量,当然此多个input之间也是相互绑定的关系。如:

此二者均对应js端的srtm变量,第一个是range类型,代表一个slide控件,第二个是一个文本框,二者相互联动,只选择其中一个控件也是可以的。重要的是data-bind属性中value后的变量名称需与js中对应。

当然也可以绑定一个下拉列表框:

这里就对应了js中的两个变量:types和selectedType。前者代表所有的可选列表及其值,后者代表选择的结果。

1.2 后台

首先创建一个viewModel对象,里面包含上述创建的各个变量,如下:

var viewModel = {    srtm: 10,    slope: 5,    types: [{                name: 'type1',                values: '100'            }, {                name: 'type2',                values: '200'            }    ],    selectedType: undefined};

而后对此变量进行监控并绑定到前台的相应控件:

Cesium.knockout.track(viewModel); // 跟踪此Modelvar toolbar = document.getElementById('toolbar'); // 获取前端监控divCesium.knockout.applyBindings(viewModel, toolbar); // 绑定监控

这样就可以监听控件的变化事件:

Cesium.knockout.getObservable(viewModel, 'srtm').subscribe(function(value) {    ...});

可以对此值进行处理比如发送到后台或者请求相应的瓦片图层等等。不过下拉列表框的情况稍微复杂点:

Cesium.knockout.getObservable(viewModel, 'selectedType').subscribe(function(options) {    var values = options.values;    ... });

其实也就是多了一步,在定义types的时候除了name变量我们还定义了values变量,此处就需要通过options.values来取出此值,其他不变。

二、 根据地形瓦片直接绘制高程、坡度及等高线

这是Cesium 1.4.0版新添加的功能,所以一定要更新到此版本。只需要正确加载地形瓦片,Cesium可以自动算出高程设色瓦片、坡度设色瓦片以及等高线。其实也不难理解,地形瓦片中包含了空三等信息,根据这些信息自然能够计算出高度图、坡度图以及等高线,先来看效果:

704456-20171220151613662-43245791.jpg

704456-20171220151658209-648678290.jpg

加载地形瓦片图层无需多言,前面已经有过介绍:

viewer.terrainProvider = new Cesium.CesiumTerrainProvider({    url : 'https://assets.agi.com/stk-terrain/v1/tilesets/world/tiles',    requestWaterMask : true,    requestVertexNormals : true});

然后就可以开始计算高程设色瓦片和坡度设色瓦片以及等高线,当然此块涉及到的东西太多,我只能凭借我粗浅的理解简单介绍,如有错误,望批评指正:

首先来看一下生成等高线:

var contourUniforms = {};material = Cesium.Material.fromType('ElevationContour');contourUniforms = material.uniforms;contourUniforms.width = 1;contourUniforms.spacing = 500;contourUniforms.color = Cesium.Color.RED;

很简单的几行代码,其中Cesium.Material.fromType函数定义如下:

Material.fromType = function(type, uniforms) {    if (!defined(Material._materialCache.getMaterial(type))) {        throw new DeveloperError('material with type \'' + type + '\' does not exist.');    }        var material = new Material({        fabric : {            type : type        }    });    if (defined(uniforms)) {        for (var name in uniforms) {            if (uniforms.hasOwnProperty(name)) {                material.uniforms[name] = uniforms[name];            }        }    }    return material;};

此函数返回一个Material对象,根据ElevationContour可以知道这是一个等高线类型的材质。uniforms是glsl着色器语言中的变量,用于控制对象颜色、位置等等。所以此处可以简单理解为得到ElevationContour类型的unifrom值并将此值作用于场景。Cesium根据此uniform生成相应类型的等高线。

理解了这一点,高程设色和坡度设色也就明白了。

高程设色如下:

var shadingUniforms = {};material = Cesium.Material.fromType('ElevationRamp');shadingUniforms = material.uniforms;shadingUniforms.minHeight = -414.0;shadingUniforms.maxHeight = 8777;

坡度设色如下:

var shadingUniforms = {};material = Cesium.Material.fromType('SlopeRamp');shadingUniforms = material.uniforms;

二者都需要为shadingUniforms变量添加一个色表:

shadingUniforms.image = getColorRamp(selectedShading);var elevationRamp = [0.0, 0.045, 0.1, 0.15, 0.37, 0.54, 1.0];var slopeRamp = [0.0, 0.29, 0.5, Math.sqrt(2)/2, 0.87, 0.91, 1.0];function getColorRamp(selectedShading) {    var ramp = document.createElement('canvas');    ramp.width = 100;    ramp.height = 1;    var ctx = ramp.getContext('2d');    var values = selectedShading === 'elevation' ? elevationRamp : slopeRamp;    var grd = ctx.createLinearGradient(0, 0, 100, 0);    grd.addColorStop(values[0], '#000000'); //black    grd.addColorStop(values[1], '#2747E0'); //blue    grd.addColorStop(values[2], '#D33B7D'); //pink    grd.addColorStop(values[3], '#D33038'); //red    grd.addColorStop(values[4], '#FF9742'); //orange    grd.addColorStop(values[5], '#ffd700'); //yellow    grd.addColorStop(values[6], '#ffffff'); //white    ctx.fillStyle = grd;    ctx.fillRect(0, 0, 100, 1);    return ramp;}

对高程和坡度归一化后的值设置颜色。这样就可以正常显示高程设色和坡度设色。

三、 同一场景下显示两个不同的瓦片图层

不是简单的两个图层叠加,而是真实的分割整个地图,左右显示两个不同的瓦片图层。效果如下:

704456-20171220151722006-607151732.jpg

首先添加两个图层,第一个创建Viewer的时候设置基础图层,第二个采用layers.addImageryProvider的方式添加(当然也可以两个都采用此种方式添加),具体添加图层的方式参考前面的博客。

layer1 = layers.addImageryProvider(...);layer2 = layers.addImageryProvider(...);

只需要设置layer1或则layer2的splitDirection属性即可:

layer2.splitDirection = Cesium.ImagerySplitDirection.LEFT;

当然还需要设置图层分割的位置:

viewer.scene.imagerySplitPosition = 0.5;

可以改变此值来改变左右图层的分割位置,0.5表示在中间。如果需要动态调整分割位置则需要加一个分割器,监听位置变化事件。整体代码如下:

前台:

#slider { position: absolute; left: 50%; top: 0px; background-color: #D3D3D3; width: 5px; height: 100%; z-index: 9999;}#slider:hover { cursor: ew-resize;}

后台:

var viewer = new Cesium.Viewer('cesiumContainer', {   baseLayerPicker: false,   imageryProvider: new Cesium.ArcGisMapServerImageryProvider({       url : 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'   })});var layers = viewer.imageryLayers;var balckMarble = layers.addImageryProvider(Cesium.createTileMapServiceImageryProvider({    url : 'https://cesiumjs.org/blackmarble',    credit : 'Black Marble imagery courtesy NASA Earth Observatory',    flipXY : true}));balckMarble.splitDirection = Cesium.ImagerySplitDirection.LEFT;var slider = document.getElementById('slider');viewer.scene.imagerySplitPosition = (slider.offsetLeft) / slider.parentElement.offsetWidth;var handler = new Cesium.ScreenSpaceEventHandler(slider);var moveActive = false;function move(movement) {    if(!moveActive) {        return;    }    var relativeOffset = movement.endPosition.x ;    var splitPosition = (slider.offsetLeft + relativeOffset) / slider.parentElement.offsetWidth;    slider.style.left = 100.0 * splitPosition + '%';    viewer.scene.imagerySplitPosition = splitPosition;}handler.setInputAction(function() {    moveActive = true;}, Cesium.ScreenSpaceEventType.LEFT_DOWN);handler.setInputAction(function() {    moveActive = true;}, Cesium.ScreenSpaceEventType.PINCH_START);handler.setInputAction(move, Cesium.ScreenSpaceEventType.MOUSE_MOVE);handler.setInputAction(move, Cesium.ScreenSpaceEventType.PINCH_MOVE);handler.setInputAction(function() {    moveActive = false;}, Cesium.ScreenSpaceEventType.LEFT_UP);handler.setInputAction(function() {    moveActive = false;}, Cesium.ScreenSpaceEventType.PINCH_END);

四、 改造geocoder控件

Cesium自带了geocoder控件,可以检索并定位到某个地址,原理很简单,就是后台解析此地址,根据解析结果将地图切换到该位置。Cesium默认采用的是微软Bing地址解析引擎,如果我们想要换成其他的如OSM或者我们自己的,只需要对此控件简单改造即可。示例代码如下:

/** * This class is an example of a custom geocoder. It provides geocoding through the OpenStreetMap Nominatim service. * @alias OpenStreetMapNominatimGeocoder * @constructor */function OpenStreetMapNominatimGeocoder() {}/** * The function called to geocode using this geocoder service. * * @param {String} input The query to be sent to the geocoder service * @returns {Promise
} */OpenStreetMapNominatimGeocoder.prototype.geocode = function (input) { var endpoint = 'https://nominatim.openstreetmap.org/search?'; var query = 'format=json&q=' + input; var requestString = endpoint + query; return Cesium.loadJson(requestString) //请求url获取json数据 .then(function (results) { var bboxDegrees; return results.map(function (resultObject) { bboxDegrees = resultObject.boundingbox; return { displayName: resultObject.display_name, destination: Cesium.Rectangle.fromDegrees( bboxDegrees[2], bboxDegrees[0], bboxDegrees[3], bboxDegrees[1] ) }; }); });};var viewer = new Cesium.Viewer('cesiumContainer', { geocoder: new OpenStreetMapNominatimGeocoder()});

首先创建了一个OpenStreetMapNominatimGeocoder类,并为其添加了geocode方法,在此方法中根据输入拼接请求url,解析结果取出经纬度、名称等内容。这样就实现了我们自己的地名解析器,其实这就是C#等语言中的父类和继承的关系。

五、 总结

本文介绍了几个Cesium的案例,都是一些比较有意思和好玩的功能,后续如果搜集到其他好玩的使用案例,同样也会总结放出。

转载于:https://www.cnblogs.com/shoufengwei/p/8073922.html

你可能感兴趣的文章
[Linux内存]linux内存学习(二)——分段和分页
查看>>
XHTML学习要点
查看>>
JavaScript的学习要点
查看>>
我用到的 Linq 扩展方法
查看>>
18.1 线程简介
查看>>
Day13
查看>>
tensorflow saver简介+Demo with linear-model
查看>>
Luogu_4103 [HEOI2014]大工程
查看>>
程序员常用软件,你用了哪些
查看>>
1043: [HAOI2008]下落的圆盘 - BZOJ
查看>>
线程同步之读写锁
查看>>
codeforces 620D Professor GukiZ and Two Arrays
查看>>
pylint
查看>>
Oracle——SQL基础
查看>>
Java设计模式(2)——工厂方法模式
查看>>
互联网基础之DIV和CSS二
查看>>
项目置顶随笔
查看>>
Redis的安装与使用
查看>>
传微软Windows Phone 7将更新支持HTML 5
查看>>
P1970 花匠
查看>>