本项目是Cesium的学习项目。Cesium是国外一个基于JavaScript编写的使用WebGL的地图引擎。Cesium支持3D,2D,2.5D形式的地图展示,可以自行绘制图形,高亮区域,并提供良好的触摸支持,且支持绝大多数的浏览器和mobile
20171227_01 搭建服务器环境,配置WebStorm对于Cesium的提示
- 场景切换: viewer.scene.camera.flyTo()
- 坐标点:Cartesian3 三维坐标标识 通过fromDegrees()静态方法转换
- 普通点:Math.toRadians()静态方法转换
### Viewer对象的属性解析
animation: false, //是否创建动画小器件,左下角仪表
baseLayerPicker: false,//是否显示图层选择器,右上角按钮
fullscreenButton: false,//是否显示全屏按钮,右下角按钮
geocoder: false,//是否显示geocoder小器件,右上角查询按钮
homeButton: true,//是否显示Home按钮,右上角按钮
infoBox : false,//是否显示信息框
sceneModePicker: false,//是否显示3D/2D选择器 ,右上角按钮
selectionIndicator : false,//是否显示选取指示器组件,绿色选中框
timeline: false,//是否显示时间轴,底部
navigationHelpButton: false,//是否显示帮助按钮,右上角按钮
imageryProvider:.... //底图数据提供
20171227_02 3D模型的添加
3d模型的添加,主要是Entity对象的添加,Viewer容器里面有一个entities属性专门来存储,使用Viewer的trackedEntity属性,追踪定位到某一模型
关于方位的解释:position、heading、pitch、roll
- position : 目标所在位置,使用Cartesian3对象表示
- heading: 朝向,保持头部水平方向不动,左右摆动,模拟船舵、车的方向盘
- pitch: 俯角,保持头部垂直方向不动,上下摆动,模拟点头、抬头
- roll: 旋转,保持头部整体不动,身体摇晃,模拟飞机的机身摆动
var position = Cesium.Cartesian3.fromDegrees(114.44024026393892, 30.44377150531985, 0); // 位置
var heading = Cesium.Math.toRadians(0); // 朝向
var pitch = Cesium.Math.toRadians(0); // 俯角
var roll = Cesium.Math.toRadians(0); // 旋绕
var hpr = new Cesium.HeadingPitchRoll(heading,pitch,roll);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr); // 方位
3d模型使用Entity对象来封装,具体的模型对象使用ModelGraphics,Entity对象不仅可以用来封装model,也可以用来封装点、线、面等其他要素
var entity = new Cesium.Entity({
name: name,
position: position,
orientation: orientation, // 这个地方的orientation不能使用object类型
model: new Cesium.ModelGraphics({
uri:"../models/" + value + ".glb" // glb格式的三维数据
})
});
20171228_01 3D模型的渲染
3D模型(ModelGraphics)的渲染分为 模型体 的渲染模式、颜色、透明度,模型轮廓的 颜色、透明度、轮廓粗细
- 模式(mode,对应colorBlendMode属性):分为高亮(ColorBlendMode.HIGHLIGHT)、替换(ColorBlendMode.REPLACE)、混合(ColorBlendMode.MIX) 三种模式, 其中,混合模式下延伸出一个特殊的属性 混合程度(对应colorBlendAmount属性,0-1,0是完全混合,只显示颜色,1只显示模型)
- 颜色(color,对应color属性):Color对象表示
- 透明度(alpha,对应color对象中的alpha属性):颜色由 R G B A 四个值代表,A就是alpha
- 轮廓颜色(color,对应silhouetteColor属性):同上
- 轮廓透明度(alpha):同上
- 轮廓粗细(size,对应silhouetteSize属性):轮廓线的粗细大小
20171228_02 3D模型的选择,场景与鼠标的交互
3d场景必不可少的需要提供与用于的交互,需要处理鼠标操作事件,Cesium提供了丰富的鼠标操作事件,所有的事件在ScreenSpaceEventType中有列举,注册处理事件的接口是Viewer对象的screenSpaceEventHandler属性
- 设置场景范围:Viewer.scene.camera.setView() 方法
- 注册鼠标事件:Viewer.screenSpaceEventHandler.setInputAction(function,type) 其中function中带有鼠标事件发生的位置(x,y)屏幕坐标
- 选择模型:Viewer.scene.pick(position) 其中position是Cartesian2对象,返回的feature对象中color属性可以用来改变颜色,getPropertyNames方法获取模型的属性名称,getProperty方法获取属性值
- pick和selectEntity的区别:pick用于选择模型,选择到的模型可以单独处理,更改颜色达到可视化效果、获取模型属性值等等;而selectEntity的作用不是用来场景选择模型的,而是只是当前场景的infoBox=true时用来显示信息框的作用,当infoBox=false时,selectEntity不起作用。
// 注册屏幕空间事件
viewer.screenSpaceEventHandler.setInputAction(function (clickEvent) {
var feature = viewer.scene.pick(clickEvent.position);
// 显示该feature
feature.color = Cesium.Color.LIME; // 更改feature的颜色
// 获取该feature的属性信息
var propertyNames = feature.getPropertyNames(); // 得到所有的属性名称
var length = propertyNames.length;
var propertyHtml = "";
for (var i = 0; i < length; ++i) {
var propertyName = propertyNames[i];
propertyHtml += "<tr><td>" + propertyName + "</td><td>" +
feature.getProperty(propertyName) + "</td></tr>";
}
var selelctEntity = new Cesium.Entity();
selelctEntity.name = feature.getProperty("name");
selelctEntity.description = "<table class='cesium-infoBox-defaultTable'><tbody> " +
propertyHtml + " </tbody></table>";
viewer.selectedEntity = selelctEntity;
}
},Cesium.ScreenSpaceEventType.LEFT_CLICK); // 左击
20180102_01 3D模型的属性分级渲染、显示影藏
这部分内容主要是针对于Cesium3DTileset对象的style属性,采用的是3D Tiles Styling Languague(3d瓦片样式语言),其中主要是针对于style属性的defines、color、show、meta四个key来展开
常用的表达式可以存储在一个defines对象中。如果一个变量引用一个定义,它将得到定义的被计算表达式的结果。如下:Height属性是模型存储的属性字段,通过defines表达式,定义了一个NewHeight新的属性,并可以在color、show、meta中的使用该属性,总结defines的作用就是提前预定义变量,把复杂的表达式通过预定义转换为简单的变量使用。
{
"defines" : {
"NewHeight" : "clamp((${Height} - 0.5) / 2.0, 1.0, 255.0)",
"HeightColor" : "rgb(${Height}, ${Height}, ${Height})"
},
"color" : {
"conditions" : [
["(${NewHeight} >= 100.0)", "color('#0000FF') * ${HeightColor}"],
["(${NewHeight} >= 50.0)", "color('#00FF00') * ${HeightColor}"],
["(${NewHeight} >= 1.0)", "color('#FF0000') * ${HeightColor}"]
]
},
"show" : "${NewHeight} < 200.0"
}
color是颜色的表示,有如下几种构造方式:
- color() : Color
- color(keyword : String, [alpha : Number]) : Color
- color(6-digit-hex : String, [alpha : Number]) : Color
- color(3-digit-hex : String, [alpha : Number]) : Color
- rgb(red : Number, green : Number, blue : number) : Color
- rgba(red : Number, green : Number, blue : number, alpha : Number) : Color
- hsl(hue : Number, saturation : Number, lightness : Number) : Color
- hsla(hue : Number, saturation : Number, lightness : Number, alpha : Number) : Color
color() 相当于 color('#FFFFFF'), 是相等的,示例:
- color('cyan')
- color('#00FFFF')
- color('#0FF')
- color('cyan', 0.5)
- rgb(100, 255, 190)
- hsl(1.0, 0.6, 0.7)
- rgba(100, 255, 190, 0.25)
- hsla(1.0, 0.6, 0.7, 0.75)
show是用来显示隐藏模型的,可以使用普通的表达式,也可以使用稍微复杂的表达式。
"show" : "true", // 显示所有对象
"show" : "${ZipCode} === '19341'" // 显示ZipCode为19341的对象
"show" : "(regExp('^Chest').test(${County})) && (${YearBuilt} >= 1970)" // 显示County属性以Chest字符开头,并且YearBuilt为1970的对象
RegExp RegExp的构造方式:
- regExp() : RegExp
- regExp(pattern : String, [flags : String]) : RegExp
regExp() 等价于 regExp('(?:)'),flags 参数有如下几种:
- g - global match 全局匹配
- i - ignore case 忽略大小写
- m - multiline
- u - unicode
- y - sticky
正则表达式支持如下几种方法: support these functions:
- test(string : String) : Boolean - 检测是否匹配
- exec(string : String) : String - 如果匹配成功,返回第一个匹配的值,否则返回null
meta是用来定义非可视化属性的,这个使用的情况少。例如:
{
"meta" : {
"description" : "'Hello, ${featureName}.'"
}
}
{
"meta" : {
"featureColor" : "rgb(${red}, ${green}, ${blue})",
"featureVolume" : "${height} * ${width} * ${depth}"
}
}
20180103_01.html 自定义terrain
自定义DEM使用的是viewer对象的terrainProvider属性设置,这个属性有 EllipsoidTerrainProvider、CesiumTerrainProvider、VRTheWorldTerrainProvider、GoogleEarthEnterpriseTerrainProvider四种实现方式,例子中采用的CesiumTerrainProvider,常用的参数说明如下:
参数 | 类型 | 含义 |
---|---|---|
url | String | The URL of the Cesium terrain server |
requestVertexNormals | Boolean | Flag that indicates if the client should request additional lighting information from the server, in the form of per vertex normals if available. |
requestWaterMask | Boolean | Flag that indicates if the client should request per tile water masks from the server, if available. |
20180104_01.html 环境要素
环境要素的模拟主要是通过viewer.scene对象的skyAtmosphere属性,分为hueShift(色调)、saturationShift(饱和度)、brightnessShift(亮度),参数值的范围为-1到1,默认为0.
同时,还可以模拟阳光的照射情况以及雾的效果,阳光主要是viewer.globle.enableLighting属性,雾是viewer.scene.fog.enabled属性,设置true或false即可。默认是不加载阳光效果,加载雾的效果。
demo_1.html 各种entity的添加
盒子(box) 圈和椭圆(ellipse) 走廊(corridor) 气缸和锥体(cylinder) 多边形(polygon) 挖洞的多边形(polygon-holes) 折线(polyline) 折线卷(polylineVolume) 矩形(rectangle) 球体和椭球体(ellipsoid) 墙壁(wall) 点(points) 广告牌(Billboards)
demo_2.html ImageryProvider
// Google
imageryProvider: new Cesium.UrlTemplateImageryProvider({
url: 'http://www.google.cn/maps/vt?lyrs=s@716&x={x}&y={y}&z={z}'
})
// ArcGIS
imageryProvider : new Cesium.ArcGisMapServerImageryProvider({
// url : 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
url : 'http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer'
}),
// BingMaps
imageryProvider: new Cesium.BingMapsImageryProvider({
url: 'https://dev.virtualearth.net',
key: 'Ao42l-0u7fJXMmQSGY0_5zW6kfuHPeTtanya4rs8bItYH982UV42_xNccLDq70lY',
mapStyle: Cesium.BingMapsStyle.AERIAL
})
// OSM
imageryProvider: Cesium.createOpenStreetMapImageryProvider({
url : 'https://a.tile.openstreetmap.org/'
})
// 天地图影像
imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
url: "http://t0.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",
layer: "tdtBasicLayer",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "GoogleMapsCompatible",
show: false
})
// 天地图注记
imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
url: "http://t0.tianditu.com/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default.jpg",
layer: "tdtAnnoLayer",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "GoogleMapsCompatible",
show: false
})
如有影像叠加的情况,可以设置透明度,显示多个
//50%透明度
blackMarble.alpha = 0.8;
//两倍亮度
blackMarble.brightness = 2.0;
单张图片,适合雷达卫星图,视频贴图
viewer.imageryLayers.addImageryProvider(new Cesium.SingleTileImageryProvider({
url : 'Cesium_Logo_Color_Overlay.png',
rectangle : Cesium.Rectangle.fromDegrees(-75.0, 28.0, -67.0, 29.75)
}));
地形:
var terrainProvider = new Cesium.CesiumTerrainProvider({
url : 'https://assets02.agi.com/stk-terrain/v1/tilesets/world/tiles',
//请求水波纹效果
requestWaterMask: true,
//请求照明
requestVertexNormals: true
});
viewer.terrainProvider = terrainProvider;
demo_3.html 实体模型的两种加载方式
entity的方式
//通过entity的方式加载3d模型
var entity = viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706),
model : {
uri : 'Cesium_Ground.gltf',
//模型颜色,透明度
color : Cesium.Color.fromAlpha(Cesium.Color.RED, parseFloat(0.5)),
//轮廓线
silhouetteColor : Cesium.Color.fromAlpha(Cesium.Color.GREEN, parseFloat(0.5)),
//模型样式 ['Highlight', 'Replace', 'Mix']
colorBlendMode : Cesium.ColorBlendMode.MIX,
//colorBlendAmount需要选择mix后将colorBlendAmountEnabled设置为true才能使用
colorBlendAmountEnabled : true,
colorBlendAmount : parseFloat(0.8)
}
});
通过primitives的方式加载
var origin = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 0);
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
var model = viewer.scene.primitives.add(Cesium.Model.fromGltf({
url: 'Cesium_Ground.gltf',
modelMatrix: modelMatrix,
minimumPixelsSize: 512,
maximumScale: 200000
}));
// 当模型准备渲染时,以半速度播放所有动画
Cesium.when(model.readyPromise).then(function (model) {
model.activeAnimations.addAll({
//这个半速是相对于Cesium的clock来说的
speedup: 0.5,
//永久重复
loop: Cesium.ModelAnimationLoop.REPEAT,
// reverse : true // Play in reverse
});
}).otherwise(function (error) {
window.alert(error);
});
demo_4.html entity和primitives的比较
// 用entity创建多个geometry
var entity = viewer.entities.add({
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0),
material: new Cesium.StripeMaterialProperty({
evenColor: Cesium.Color.WHITE,
oddColor: Cesium.Color.BLUE,
repeat: 5 // 重复5条
})
}
});
for (var lon = -180.0; lon < 180.0; lon += 5.0) {
for (var lat = -85.0; lat < 85.0; lat += 5.0) {
viewer.entities.add({
rectangle: new Cesium.RectangleGraphics({
coordinates: Cesium.Rectangle.fromDegrees(lon, lat, lon + 5.0, lat + 5.0),
material: new Cesium.ColorMaterialProperty(Cesium.Color.fromRandom({alpha: 0.5})),
outline: true,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 1.5
})
})
}
}
// 用primitives创建多个geomerty
var instances = [];
//循环创建随机颜色的矩形
for (var lon = -180.0; lon < 180.0; lon += 5.0) {
for (var lat = -85.0; lat < 85.0; lat += 5.0) {
instances.push(new Cesium.GeometryInstance({
id: Cesium.Math.nextRandomNumber(),
geometry: new Cesium.RectangleGeometry({
rectangle: Cesium.Rectangle.fromDegrees(lon, lat, lon + 5.0, lat + 5.0),
vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
}),
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromRandom({alpha: 0.5}))
}
}));
}
}
scene.primitives.add(new Cesium.Primitive({
geometryInstances: instances,
appearance: new Cesium.PerInstanceColorAppearance() //使用PerInstanceColorAppearance不同颜色来遮蔽每个实例
}));
这样的写法自然是有优点也有缺点的(摘抄)
- 优点:
性能 - 当绘制大量静态图元时,直接使用几何形状可以将它们组合成单个几何体,以减少CPU开销并更好地利用GPU。并且组合是在网络上完成的,可以保持UI的响应。 灵活性 - 基元组合几何和外观。通过解耦,我们可以独立地修改。我们可以添加与许多不同外观兼容的新几何体,反之亦然。 低级访问 - 外观提供了接近于渲染器的访问,可以直接使用渲染器的所有细节(Appearances provide close-to-the-metal access to rendering without having to worry about all the details of using the Renderer directly)。外观使其易于: 编写完整的GLSL顶点和片段着色器。 使用自定义渲染状态。
- 缺点:
代码量增大,并且需要使用者对这方面有更深入的理解。 组合几何可以使用静态数据,不一定是动态数据。 primitives 的抽象级别适合于映射应用程序;几何图形和外观的抽象层次接近传统的3D引擎(Primitives are at the level of abstraction appropriate for mapping apps; geometries and appearances have a level of abstraction closer to a traditional 3D engine)(感觉翻译的不太好的地方都给上了原文)
demo_5.html 粒子系统
粒子系统的起步从官网的Interpolation例子开始
- 设置animation和timeline
- 设置timeline的时间范围,循环方式,频率
- 计算时间段内每个时间,模型所在的位置
- 添加模型
- 设置曲线插值方式
根据这几部就能让模型动起来,接下来撸 Particle System 真正的粒子例子
// 粒子系统
var particleSystem = viewer.scene.primitives.add(new Cesium.ParticleSystem({
image: 'fire.png', // 粒子资源,用于广告牌的URI,HTMLImageElement或HTMLCanvasElement。
startColor: Cesium.Color.RED.withAlpha(0.7), //粒子出生时的颜色
endColor: Cesium.Color.YELLOW.withAlpha(0.3), //当粒子死亡时的颜色
startScale: 1, //粒子出生时的比例,相对于原始大小
endScale: 4, //粒子在死亡时的比例
life: 1, //以秒为单位设置粒子的最小和最大寿命
// minimumLife: 1, //以秒为单位设置粒子的最短寿命
// maximumLife: 1, //以秒为单位设置粒子的最大寿命
speed: 5,//设置以米/秒为单位的最小和最大速度
// minimumSpeed: 5, //设置以米/秒为单位的最小速度
// maximumSpeed: 5, //设置以米/秒为单位的最大速度
width: 20, // 设置以像素为单位的粒子的最小和最大宽度
// minimumWidth: viewModel.particleSize, //设置粒子的最小宽度(以像素为单位)。
// maximumWidth: viewModel.particleSize, //设置粒子的最大宽度(以像素为单位)。
height: 20, //设置粒子的最小和最大高度(以像素为单位)。
// minimumHeight: viewModel.particleSize, //设置粒子的最小高度(以像素为单位)。
// maximumHeight: viewModel.particleSize, //设置粒子的最大高度(以像素为单位)。
rate: 10, //每秒发射的粒子数量
// bursts: [
// // time:在粒子系统生命周期开始之后的几秒钟内将发生突发事件。
// // minimum:突发中发射的最小粒子数量
// // maximum:突发中发射的最大粒子数量
// // new Cesium.ParticleBurst({time: 5.0, minimum: 1, maximum: 10}), // 当在5秒时,发射的数量为50-100
// // new Cesium.ParticleBurst({time: 10.0, minimum: 1, maximum: 10}), // 当在10秒时,发射的数量为200-300
// // new Cesium.ParticleBurst({time: 15.0, minimum: 1, maximum: 10}) // 当在15秒时,发射的数量为500-800
// new Cesium.ParticleBurst({time: 5.0, minimum: 50, maximum: 100}), // 当在5秒时,发射的数量为50-100
// new Cesium.ParticleBurst({time: 10.0, minimum: 100, maximum: 200}), // 当在10秒时,发射的数量为200-300
// new Cesium.ParticleBurst({time: 15.0, minimum: 200, maximum: 300}) // 当在15秒时,发射的数量为500-800
// ], //数组ParticleBurst,周期性地发射粒子脉冲串
lifeTime: 16, //多长时间的粒子系统将以秒为单位发射粒子
loop: true, //是否粒子系统应该在完成时循环它的爆发
// new Cesium.CircleEmitter(0.5)
// new Cesium.BoxEmitter(new Cesium.Cartesian3(0.1, 0.1, 0.1))
// new Cesium.ConeEmitter(Cesium.Math.toRadians(30.0))
emitter: new Cesium.CircleEmitter(0.5), //此系统的粒子发射器 共有 BoxEmitter,CircleEmitter,ConeEmitter,SphereEmitter 几类
emitterModelMatrix: computeEmitterModelMatrix(), // 4x4转换矩阵,用于在粒子系统本地坐标系中转换粒子系统发射器
modelMatrix: computeModelMatrix(entity, Cesium.JulianDate.now()), // 4x4转换矩阵,可将粒子系统从模型转换为世界坐标
forces: [applyGravity] // 强制回调函数--例子:这是添加重力效果
}));
// 计算模型位置
function computeModelMatrix(entity, time) {
var position = Cesium.Property.getValueOrUndefined(entity.position, time, new Cesium.Cartesian3());
if (!Cesium.defined(position)) {
return undefined;
}
var orientation = Cesium.Property.getValueOrUndefined(entity.orientation, time, new Cesium.Quaternion());
var modelMatrix = null;
if (!Cesium.defined(orientation)) {
modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position, undefined, new Cesium.Matrix4());
} else {
modelMatrix = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromQuaternion(orientation, new Cesium.Matrix3()), position, modelMatrix);
}
return modelMatrix;
}
// 计算粒子发射系统的模型位置
function computeEmitterModelMatrix() {
var hpr = Cesium.HeadingPitchRoll.fromDegrees(0, 0, 0, new Cesium.HeadingPitchRoll());
var trs = new Cesium.TranslationRotationScale();
trs.translation = Cesium.Cartesian3.fromElements(2.5, 4.0, 1.0, new Cesium.Cartesian3()); // 设置粒子系统相对于模型坐标的偏移
trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr, new Cesium.Quaternion());
return Cesium.Matrix4.fromTranslationRotationScale(trs, new Cesium.Matrix4());
}
/**
* 用于在每个时间步上对粒子施加力的函数
* @param particle 要施加力的粒子
* @param dt 自上次更新以来的时间
*/
function applyGravity(particle, dt) {
var position = particle.position;
var gravityVector = Cesium.Cartesian3.normalize(position, new Cesium.Cartesian3());
Cesium.Cartesian3.multiplyByScalar(gravityVector, 0 * dt, gravityVector); // 设置重力效果大小 -20时效果比较明显
particle.velocity = Cesium.Cartesian3.add(particle.velocity, gravityVector, particle.velocity);
}
// 当场景运动起来时,粒子系统要实时计算位置,静止的场景可以省略这个
viewer.scene.preRender.addEventListener(function (scene, time) {
particleSystem.modelMatrix = computeModelMatrix(entity, time);
particleSystem.emitterModelMatrix = computeEmitterModelMatrix();
});
demo_6.html 制作雨天效果
为了加深对例子系统的理解,做了一个雨天效果
1、随机在设定好的下雨的范围生成n个雨点
// 随机的entity
var entities = [];
for (var lon = 114.0; lon < 114.1; lon += 0.01) {
for (var lat = 30.0; lat < 30.1; lat += 0.01) {
entities.push(viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees((lon + lon + 0.01) / 2, (lat + lat + 0.01) / 2, 10000),
point: {
pixelSize: 5,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
show: false
}
}));
}
}
2、每个雨点加载一个粒子系统
for (var i = 0; i < entities.length; i++) {
viewer.scene.primitives.add(new Cesium.ParticleSystem({
image: 'rainy.png', // 雨点图片
startColor: Cesium.Color.GHOSTWHITE,
endColor: Cesium.Color.GHOSTWHITE,
startScale: 1,
endScale: 1,
life: 20,
speed: Math.floor(Math.random() * 20 + 1),//随机速度
width: 10, // 设置以像素为单位的粒子的最小和最大宽度
height: 10, //设置粒子的最小和最大高度(以像素为单位)。
rate: 1, //每秒发射的粒子数量
lifeTime: 16, //多长时间的粒子系统将以秒为单位发射粒子
loop: true, //是否粒子系统应该在完成时循环它的爆发
emitter: new Cesium.CircleEmitter(0.5),
emitterModelMatrix: computeEmitterModelMatrix(),
modelMatrix: computeModelMatrix(entities[i], Cesium.JulianDate.now()),
forces: [applyGravity]
}))
}
demo_6_1.html 雨天粒子效果2
demo_6中通过添加entity的方式,给每个entity添加一个粒子系统,在6_1中,只添加了一个entity, 然后每个粒子通过位置偏移来定位,减少entity的消耗
1、制定模型位置
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(114.0, 30.0));
2、定义偏移范围
var minX = -1000.0;
var maxX = 1000.0;
var minY = -800.0;
var maxY = 1000.0;
var minZ = -500.0;
var maxZ = 500.0;
3、计算偏移
var x = Cesium.Math.randomBetween(minX, maxX);
var y = Cesium.Math.randomBetween(minY, maxY);
var z = Cesium.Math.randomBetween(minZ, maxZ);
var height = Cesium.Math.randomBetween(800, 1000);
var offset = new Cesium.Cartesian3(x, y, z);
4、计算粒子系统位置
var position = Cesium.Cartesian3.add(new Cesium.Cartesian3(0.0, 0.0, height), offset, new Cesium.Cartesian3());
var emitterMatrix = Cesium.Matrix4.fromTranslation(position, new Cesium.Matrix4());
demo_7.html 官网烟花粒子系统
demo_8.html entity叠加视频
这个例子可以模拟广场大屏放电影的效果,视频叠加到模型上。
build.html 模拟无人机在巡航时,能够照射的范围
两个entity的叠加