# 效果

Cesium-雷达遮罩动态扫描_5e

最终完整代码请看下面的封装一栏

# 基本思路

我们将他分为两个步骤来做第一步加载一个ellipsoid加载半圆体,第二步用cesium提供的wall属性加载一个立体墙,运用cesium提供的viewer.clock.onTick开启动画效果听起来很简单。下面我们来进行实现

# 实现方法

第一步我们先用cesium中提供ellipsoid方法加载半圆体,先看一下ellipsoid中都有哪些属性

属性名

属性含义

distanceDisplayCondition

指定将在距相机多远的距离显示和隐藏 new Cesium.DistanceDisplayCondition(0.0,10.5e6 ),

fill

设置填充色显示隐藏

heightReference

默认值: HeightReference.NONE

innerRadii

指定椭圆体的内半径 默认值: radii

material

设置球体材质 如:new Cesium.Color.fromCssColorString("#00dcff82")

maximumClock

设置指定椭球最大时钟角的属性

maximumCone

指定椭圆体最大锥角的属性 如:Cesium.Math.toRadians(90)

minimumClock

设置指定椭球最小时钟角的属性

minimumCone

指定椭圆体最小锥角的属性

outline

设置指定corridor 是否有轮廓的Property 。true或false

outlineColor

轮廓线颜色

outlineWidth

轮廓线宽度

radii

设置指定椭圆体的半径。 Cartesian3 Property

shadows

设置阴影 默认值: ShadowMode.DISABLED

show

设置实体显示隐藏

slicePartitions

设置指定每 360 度的径向切片数的属性 默认值: 64

stackPartitions

设置指定堆栈数的属性 默认值: 64

subdivisions

指定每个轮廓环的样本数,确定曲率的粒度 默认值: 128

viewer.entities.add({



position: Cesium.Cartesian3.fromDegrees(
-80,
35
),
ellipsoid: {



radii: new Cesium.Cartesian3(
100000.0,
100000.0,
100000.0
),
maximumCone: Cesium.Math.toRadians(90),
material: new Cesium.Color.fromCssColorString("#00dcff82"),
outline: true,
outlineColor: new Cesium.Color.fromCssColorString("#00dcff82"),
outlineWidth: 1,
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
0.0,
10.5e6
),
},
});


现在我们就行看见一个静态的半球体

Cesium-雷达遮罩动态扫描_默认值_02

第二步我们cesium中提供的wall来加载里面类似扇叶在动的东西,先不着急写代码,我们先来看一下wall里面的属性值

属性

含义值

material

设置材质

maximumHeights

用于墙顶的高度数组,而不是每个位置的高度

minimumHeights

用于墙底的高度数组

outline

设置指定corridor 是否有轮廓的Property 默认

outlineColor

轮廓线颜色

outlineWidth

轮廓线宽度

fill

设置填充色显示隐藏

distanceDisplayCondition

new Cesium.DistanceDisplayCondition( 0.0, 5.5e6 )距相机多远的距离处显示或隐藏

shadows

ShadowMode.DISABLED设置投影

show

true或false实体显示隐藏(动态改变直接改变show就可以)

注意wall加载出来的立体墙并不不是我们想要的,看图我们可以知道我们想要一个1/4圆形立体墙,我们可以通过两个算法来得到,我们分为两步第一步先来确定平面扫描区域,在来确定里面扫描区域。

先来确定平面扫描区域

// 根据第一个点 偏移距离 角度 求取第二个点的坐标
function calcPoints(x1, y1, radius, heading){



var m = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(x1, y1));
var rx = radius * Math.cos(heading * Math.PI / 180.0);
var ry = radius * Math.sin(heading * Math.PI / 180.0);
var translation = Cesium.Cartesian3.fromElements(rx, ry, 0);
var d = Cesium.Matrix4.multiplyByPoint(m, translation, new Cesium.Cartesian3());
var c = Cesium.Cartographic.fromCartesian(d);
var x2 = Cesium.Math.toDegrees(c.longitude);
var y2 = Cesium.Math.toDegrees(c.latitude);
return computeCirclularFlight(x1, y1, x2, y2, 0, 90);
}


确定立面扫描区域

// 根据两个点 开始角度、夹角度 求取立面的扇形
function computeCirclularFlight(x1, y1, x2, y2, fx, angle) {



let positionArr = [];
positionArr.push(x1);
positionArr.push(y1);
positionArr.push(0);
var radius = Cesium.Cartesian3.distance(Cesium.Cartesian3.fromDegrees(x1, y1), Cesium.Cartesian3.fromDegrees(x2, y2));
for (let i = fx; i <= fx + angle; i++) {



let h = radius * Math.sin(i * Math.PI / 180.0);
let r = Math.cos(i * Math.PI / 180.0);
let x = (x2 - x1) * r + x1;
let y = (y2 - y1) * r + y1;
positionArr.push(x);
positionArr.push(y);
positionArr.push(h);
}
return positionArr;
}


然后来进行加载立体墙

// An highlighted block
viewer.entities.add({



position: Cesium.Cartesian3.fromDegrees(
-80,
35
),
wall: {



positions: new Cesium.CallbackProperty(() => {



return Cesium.Cartesian3.fromDegreesArrayHeights(positionArr);
}, false),
material: new Cesium.Color.fromCssColorString("#00dcff82"),
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
0.0,
10.5e6
),
},
});
var heading = 0;
var positionArr = calcPoints(
-80,
35,
100000.0,//此处芋圆的半径保持一致
heading
);


此时我们可以看到一个静态的效果已经出来了,但是还出现了一个问题他并没有动,没有达到我们想要的效果如下图所示

Cesium-雷达遮罩动态扫描_Cesium_03

我们在仔细观察cesium文档中给我们提供了一个viewer.clock.onTick方法

viewer.clock.onTick.addEventListener(() => {



heading += 10.0;
positionArr = calcPoints(
-80,
35,
100000.0,
heading
);
});


现在我们的动画效果就出现了,来看一眼完整代码

viewer.entities.add({



position: Cesium.Cartesian3.fromDegrees(
-80,
35
),
wall: {



positions: new Cesium.CallbackProperty(() => {



return Cesium.Cartesian3.fromDegreesArrayHeights(positionArr);
}, false),
material: new Cesium.Color.fromCssColorString("#00dcff82"),
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
0.0,
10.5e6
),
},
ellipsoid: {



radii: new Cesium.Cartesian3(
100000.0,
100000.0,
100000.0
),
maximumCone: Cesium.Math.toRadians(90),
material: new Cesium.Color.fromCssColorString("#00dcff82"),
outline: true,
outlineColor: new Cesium.Color.fromCssColorString("#00dcff82"),
outlineWidth: 1,
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
0.0,
10.5e6
),
},
});
var heading = 0;
var positionArr = calcPoints(
-80,
35,
100000.0,//此处芋圆的半径保持一致
heading
);
viewer.clock.onTick.addEventListener(() => {



heading += 10.0;
positionArr = calcPoints(
-80,
35,
100000.0,
heading
);
});
function calcPoints(x1, y1, radius, heading){



var m = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(x1, y1));
var rx = radius * Math.cos(heading * Math.PI / 180.0);
var ry = radius * Math.sin(heading * Math.PI / 180.0);
var translation = Cesium.Cartesian3.fromElements(rx, ry, 0);
var d = Cesium.Matrix4.multiplyByPoint(m, translation, new Cesium.Cartesian3());
var c = Cesium.Cartographic.fromCartesian(d);
var x2 = Cesium.Math.toDegrees(c.longitude);
var y2 = Cesium.Math.toDegrees(c.latitude);
return computeCirclularFlight(x1, y1, x2, y2, 0, 90);
}
function computeCirclularFlight(x1, y1, x2, y2, fx, angle) {



let positionArr = [];
positionArr.push(x1);
positionArr.push(y1);
positionArr.push(0);
var radius = Cesium.Cartesian3.distance(Cesium.Cartesian3.fromDegrees(x1, y1), Cesium.Cartesian3.fromDegrees(x2, y2));
for (let i = fx; i <= fx + angle; i++) {



let h = radius * Math.sin(i * Math.PI / 180.0);
let r = Math.cos(i * Math.PI / 180.0);
let x = (x2 - x1) * r + x1;
let y = (y2 - y1) * r + y1;
positionArr.push(x);
positionArr.push(y);
positionArr.push(h);
}
return positionArr;
}


哇这代码看起来很乱,不便于后期维护,我们可以对其进行封装一下 ,让代码更加美观

# 封装

我们用es6 class对其进行封装,我们先命名一个js文件,trackMatte.js

/**
*
* @param {Viewer} viewer
* @param {Cartesian3} position 经纬度
* @param {String} id
* @param {number} shortwaveRange 半径
* @return {*}
*
*/

export default class TrackMatte {



constructor(val) {



this.viewer = val.viewer;
this.id = val.id;
this.shortwaveRange = val.shortwaveRange;
this.longitude = val.position[0],
this.latitude = val.position[1],
this.position = Cesium.Cartesian3.fromDegrees(
val.position[0],
val.position[1],
);
this.heading = 0;
this.positionArr = this.calcPoints(
val.position[0],
val.position[1],
val.shortwaveRange,
0
) //储存脏数据
this.addEntities()
}
addEntities(){



let entity = this.viewer.entities.add({



id: this.id,
position: this.position,
wall: {



positions: new Cesium.CallbackProperty(() => {



return Cesium.Cartesian3.fromDegreesArrayHeights(this.positionArr);
}, false),
material: new Cesium.Color.fromCssColorString("#00dcff82"),
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
0.0,
10.5e6
),
},
ellipsoid: {



radii: new Cesium.Cartesian3(
this.shortwaveRange,
this.shortwaveRange,
this.shortwaveRange
),
maximumCone: Cesium.Math.toRadians(90),
material: new Cesium.Color.fromCssColorString("#00dcff82"),
outline: true,
outlineColor: new Cesium.Color.fromCssColorString("#00dcff82"),
outlineWidth: 1,
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
0.0,
10.5e6
),
},
});
this.addPostRender()
}
addPostRender(){



this.viewer.clock.onTick.addEventListener(() => {



this.heading += 10.0;//可调节转动速度
this.positionArr = this.calcPoints(
this.longitude,
this.latitude,
this.shortwaveRange,
this.heading
);
});
}
calcPoints(x1, y1, radius, heading) {



var m = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(x1, y1)
);
var rx = radius * Math.cos((heading * Math.PI) / 180.0);
var ry = radius * Math.sin((heading * Math.PI) / 180.0);
var translation = Cesium.Cartesian3.fromElements(rx, ry, 0);
var d = Cesium.Matrix4.multiplyByPoint(
m,
translation,
new Cesium.Cartesian3()
);
var c = Cesium.Cartographic.fromCartesian(d);
var x2 = Cesium.Math.toDegrees(c.longitude);
var y2 = Cesium.Math.toDegrees(c.latitude);
return this.computeCirclularFlight(x1, y1, x2, y2, 0, 90);
}
computeCirclularFlight(x1, y1, x2, y2, fx, angle) {



let positionArr = [];
positionArr.push(x1);
positionArr.push(y1);
positionArr.push(0);
var radius = Cesium.Cartesian3.distance(
Cesium.Cartesian3.fromDegrees(x1, y1),
Cesium.Cartesian3.fromDegrees(x2, y2)
);
for (let i = fx; i <= fx + angle; i++) {



let h = radius * Math.sin((i * Math.PI) / 180.0);
let r = Math.cos((i * Math.PI) / 180.0);
let x = (x2 - x1) * r + x1;
let y = (y2 - y1) * r + y1;
positionArr.push(x);
positionArr.push(y);
positionArr.push(h);
}
return positionArr;
}

}


最后我们只需在我们页面中引用即可

import TrackMatte from "./trackMatte.js"
trackMatte(){



let trackMatte = new TrackMatte({



viewer:viewer,
id:1,
shortwaveRange:100000.0,
position:[-80,35],
})
}


至此我们我们的效果就与开始图中的效果一摸一样了。大功告成