本文共 3884 字,大约阅读时间需要 12 分钟。
作者:kele
在三维地理信息系统中,河流是重要的组成部分,如何在三维场景中展示河流成为我们重点探讨的对象;在以往的方法中,我们可以通过iDesktop制作水面特效来展示河流,但这种方式的局限性在于不能改变河流的走向以及水流的方向,今天,小编为大家介绍一种前端绘制河流的方法~
1.绘制entity实体线
2.给实体线赋予动态材质贴图 3.根据相机高度改变实体线宽 其中主要的障碍应该是第二点,如何自定义动态纹理材质,我们一起来看下吧1.构建自定义动态纹理材质
color:材质颜色 duration:纹理流动循环周期 texture2D(image, vec2(fract(st.s5.0-time1.0), st.t)):纹理运动方向及速度function PolylineTrailLinkMaterialProperty(color, duration) { this._definitionChanged = new Cesium.Event(); this._color = undefined; this._colorSubscription = undefined; this.color = color; this.duration = duration; this._time = (new Date()).getTime();}Object.defineProperties(PolylineTrailLinkMaterialProperty.prototype, { isConstant: { get: function () { return false; } }, definitionChanged: { get: function () { return this._definitionChanged; } }, color: Cesium.createPropertyDescriptor('color')});PolylineTrailLinkMaterialProperty.prototype.getType = function (time) { return 'PolylineTrailLink';};PolylineTrailLinkMaterialProperty.prototype.getValue = function (time, result) { if (!Cesium.defined(result)) { result = { }; } result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color); result.image = Cesium.Material.PolylineTrailLinkImage; result.time = (((new Date()).getTime() - this._time) % this.duration) / this.duration; return result;};PolylineTrailLinkMaterialProperty.prototype.equals = function (other) { return this === other || (other instanceof PolylineTrailLinkMaterialProperty && Property.equals(this._color, other._color))};Cesium.PolylineTrailLinkMaterialProperty = PolylineTrailLinkMaterialProperty;Cesium.Material.PolylineTrailLinkType = 'PolylineTrailLink';Cesium.Material.PolylineTrailLinkImage = "./images/movingRiver.png";Cesium.Material.PolylineTrailLinkSource = "\ uniform vec4 color;\n\ uniform float time;\n\ uniform sampler2D image;\n\ czm_material czm_getMaterial(czm_materialInput materialInput)\n\ {\n\ czm_material material = czm_getDefaultMaterial(materialInput);\n\ vec2 st = materialInput.st;\n\ vec4 colorImage = texture2D(image, vec2(fract(st.s*5.0-time*1.0), st.t));\n\ material.alpha = colorImage.a * color.a;\n\ material.diffuse = colorImage.rgb;\n\ return material;\n\ }";Cesium.Material._materialCache.addMaterial(Cesium.Material.PolylineTrailLinkType, { fabric: { type: Cesium.Material.PolylineTrailLinkType, uniforms: { color: new Cesium.Color(1.0, 0.0, 0.0, 0.5), image: Cesium.Material.PolylineTrailLinkImage, time: 0, repeat: 3 }, source: Cesium.Material.PolylineTrailLinkSource }, translucent: function (material) { return true; }});
2.绘制实体线,并赋予第一步定义的材质
river = viewer.entities.add({ name : 'river', polyline : { positions : new Cesium.Cartesian3.fromDegreesArrayHeights(positions), width: 20, followSurface : true, material : new Cesium.PolylineTrailLinkMaterialProperty(Cesium.Color.SKYBLUE,10000), clampToGround: true, distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 30000) }});
因为polyline的线宽是像素宽度,不会随着场景高度变化而变化,导致在场景缩放过程中河流宽度不真实,我们用以下方法来动态改变河流宽度
scene.postRender.addEventListener(function(){ // 每一帧都去计算气泡的正确位置 if(flag === true){ var position = viewer.scene.camera._position; var cartographic = Cesium.Cartographic.fromCartesian(position); var currtenHeight = cartographic.height; for(var i=1;i<=10;i++){ if(currtenHeight>=perHeight*i && currtenHeight<=(perHeight*i+perHeight)){ if(currtenHeight<3500){ river.polyline.width = maxWidth } else if(currtenHeight>3500 && river.polyline.width._value !== maxWidth-perWidth*i){ river.polyline.width = maxWidth-perWidth*i } } } }});
转载地址:http://uvpxi.baihongyu.com/