let viewer;
/**
* 初始化cesium
* id 容器id
*/
function initCesium(id) {
//地图对象
Cesium.Ion.defaultAccessToken = 'xxx';//用自己的token
//定义生成器
let pinBuilder = new Cesium.PinBuilder();
//--------------------------------声明全局变量结束--------------------------------------------------------
viewer = new Cesium.Viewer(id, {
contextOptions: {
//cesium状态下允许canvas转图片convertToImage
webgl: {
alpha: true,
depth: false,
stencil: true,
antialias: true,
premultipliedAlpha: true,
preserveDrawingBuffer: true,
failIfMajorPerformanceCaveat: true
},
allowTextureFilterAnisotropic: true
},
animation: false,//是否创建动画小器件,左下角仪表
fullscreenButton: true,//是否显示全屏按钮
shouldAnimate: true,//设置停止
timeline: true,//是否显示时间轴
geocoder: false,//是否显示geocoder小器件,右上角查询按钮
homeButton: false,//是否显示Home按钮
//shadows:true,
infoBox: false, //点击要素之后显示的信息,默认true
navigationHelpButton: false,//是否显示右上角的帮助按钮
baseLayerPicker: false, //地图切换控件(底图以及地形图)是否显示,默认显示true
sceneModePicker: false, //是否显示投影方式控件
terrainProvider: Cesium.createWorldTerrain()
});
viewer._cesiumWidget._creditContainer.style.display = "none";
}
上面的函数调用后就能看见地球了,记得token用自己注册的那个
/**
* 点击地图事件
*/
function handlerPick() {
handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);//可以做成一个全局变量
handler.setInputAction(function (e) {
var camera = viewer.scene.camera;
var pick = viewer.scene.pick(e.position);
//获取点击位置笛卡尔坐标
var position = viewer.scene.pickPosition(e.position);
//将笛卡尔坐标转化为经纬度坐标
var cartographic = Cesium.Cartographic.fromCartesian(position);
var longitude = Cesium.Math.toDegrees(cartographic.longitude);//经度值
var latitude = Cesium.Math.toDegrees(cartographic.latitude);//纬度值
var height = viewer.scene.globe.getHeight(cartographic);//高度
console.log('经度:' + longitude + ',纬度:' + latitude + ',高度:' + height);
console.log(pick);//最常用的,pick相当于js里的target,可以打印看看
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
/**
* cesium鼠标移动
*/
function cesiumMouseMove(){
let handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function (movement) {
var pick= viewer.scene.pick(movement.endPosition);
console.log(pick);//这个pick和地图点击出来的pick一样
}
function create3dtiles(viewer) {
//设置时间
var tilesetQX;
tilesetQX_URL = new Cesium.Cesium3DTileset({
url: "http://localhost:9001/cesium/static/resource/3dtiles/tileset.json "
});
tilesetQX = viewer.scene.primitives.add(tilesetQX_URL);
viewer.zoomTo(tilesetQX);
return tilesetQX;
}
//可以在初始化的时候调用,加载自己的3dtiles
/*
*地址,经纬度和高度
*/
function loadGltf(url, lat, lon, height) {
let modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(lat, lon, height)); //gltf数据加载位置
return viewer.scene.primitives.add(Cesium.Model.fromGltf({
url: url, //如果为bgltf则为.bgltf
modelMatrix: modelMatrix,
scale: 0.01 //放大倍数
}));
}
/**
* 加载模型glb
* @param position
* @param url
* @param id
* @param name
*/
function loadGlb(position, url, id, name) {
return viewer.entities.add({
name: name,
id: id,
position: position,
model: {
uri: url
}
});
}
/**
* 加载火焰效果
*/
function createParticleFire() {
let fire = {
position: { x: -2334003.917793716, y: 4560141.505329625, z: 3787194.4287287444 },
image: 'http://localhost:9001/cesium/static/resource/img/fire.png'
}
var entity = viewer.entities.add({ position: fire.position, label: { text: " '' " } });
function computeModelMatrix(entity, time) {
var position = Cesium.Property.getValueOrUndefined(entity.position);
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position);
return modelMatrix;
}
function computeEmitterModelMatrix() {
var hpr = Cesium.HeadingPitchRoll.fromDegrees(0, 0, 0);
var trs = new Cesium.TranslationRotationScale();
trs.translation = Cesium.Cartesian3.fromElements(2.5, 4, 1);
trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr);
var result = Cesium.Matrix4.fromTranslationRotationScale(trs);
return result;
}
var viewModel = {
emissionRate: 5.0,
gravity: 0.0,
minimumParticleLife: 5.0,
maximumParticleLife: 5.0,
minimumSpeed: 1.0,
maximumSpeed: 1.0,
startScale: 1.0,
endScale: 4.0,
particleSize: 20.0,
transX: 2.5,
transY: 4.0,
transZ: 1.0,
heading: 0.0,
pitch: 0.0,
roll: 0.0,
fly: true,
spin: true,
show: true
};
var primitive = viewer.scene.primitives.add(
new Cesium.ParticleSystem({
image: fire.image,
startColor: Cesium.Color.RED.withAlpha(0.7), //粒子出生时的颜色
endColor: Cesium.Color.YELLOW.withAlpha(0.3), //当粒子死亡时的颜色
startScale: viewModel.startScale, //粒子出生时的比例,相对于原始大小
endScale: viewModel.endScale, //粒子在死亡时的比例
minimumParticleLife: viewModel.minimumParticleLife, //设置粒子寿命的可能持续时间的最小界限(以秒为单位),粒子的实际寿命将随机生成
maximumParticleLife: viewModel.maximumParticleLife, //设置粒子寿命的可能持续时间的最大界限(以秒为单位),粒子的实际寿命将随机生成
minimumSpeed: viewModel.minimumSpeed, //设置以米/秒为单位的最小界限,超过该最小界限,随机选择粒子的实际速度。
maximumSpeed: viewModel.maximumSpeed, //设置以米/秒为单位的最大界限,超过该最大界限,随机选择粒子的实际速度。
imageSize: new Cesium.Cartesian2(viewModel.particleSize, viewModel.particleSize), //如果设置该属性,将会覆盖 minimumImageSize和maximumImageSize属性,以像素为单位缩放image的大小
emissionRate: viewModel.emissionRate, //每秒发射的粒子数。
lifetime: 16.0, //多长时间的粒子系统将以秒为单位发射粒子
emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(0.5)), //此系统的粒子发射器 共有 圆形、锥体、球体、长方体 ( BoxEmitter,CircleEmitter,ConeEmitter,SphereEmitter ) 几类
modelMatrix: computeModelMatrix(entity, Cesium.JulianDate.now()), // 4x4转换矩阵,可将粒子系统从模型转换为世界坐标
emitterModelMatrix: computeEmitterModelMatrix() // 4x4转换矩阵,用于在粒子系统本地坐标系中转换粒子系统发射器
})
);
entity.remove = function () {
viewer.entities.remove(entity);
viewer.scene.primitives.remove(primitive);
};
return entity;
}
/**
* 模型移动
*/
/*
1.入参对象结构
let modelAttribute={
modelId:modelMove.clickMoxing.id._id,//模型的id
modelUrl:modelMove.clickMoxing.primitive._resource._url,//模型的地址
timePositions:modelMove.modelMovePositions.get(modelMove.clickMoxing.id._id).timePositions,//设置的位置,包括里面的时间
time:modelMove.modelMovePositions.get(modelMove.clickMoxing.id._id).time,//总时间
isGroup:group.isGroup//模型的分组
}
2.timePositions解释
第一个点到第二个点,这路程需要时间,比如5秒走完,那这里需要设置两个点:起点的经纬度和高度,tiem设置为0,终点的经纬度和高度,time设置为50(毫秒)
timePositions的结构:
timePositions=[{longitude: lon, dimension: lat, height: height, time: 0},{longitude: lon, dimension: lat, height: height, time: 50}]
3.time解释
time是走完几段路所使用最大时间
一段路曾走完后,比如走了两段路,3个点,每段路5秒走完,那么这两端路则10秒走完,那么下面设置结束时间则为他起始时间+10秒,所以每加一个点就要更新这个时间
time结构:
tiem=50;
4.isGroup解释
用来给模型分组使用
例如把加载的模型分为2个组,a组b组,设置模型的parent属性
group1=viewer.entities.add(new Cesium.Entity());
group2=viewer.entities.add(new Cesium.Entity());
if(true){
entity.parent=group1;
}else{
eneity.parent=group2;
}
isGroup结构:
isGroup='redGroup'
*/
function modelMovement(modelAttribute) {
//modelId模型id
//拿到模型
let model = viewer.entities.getById(modelAttribute.modelId);
let modelName=model._name;
//拿到选中模型属性,后面重新放入
let data = [modelAttribute.timePositions];
//移除选中模型
viewer.entities.remove(model);
// 起始时间
let start = Cesium.JulianDate.fromDate(new Date(2017, 7, 11));
// 结束时间
let stop = Cesium.JulianDate.addSeconds(start, modelAttribute.time, new Cesium.JulianDate());
// 设置始时钟始时间
viewer.clock.startTime = start.clone();
// 设置时钟当前时间
viewer.clock.currentTime = start.clone();
// 设置始终停止时间
viewer.clock.stopTime = stop.clone();
// 时间速率,数字越大时间过的越快
viewer.clock.multiplier = 10;
// 时间轴
viewer.timeline.zoomTo(start, stop);
// 循环执行,即为2,到达终止时间,重新从起点时间开始
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
for (let j = 0; j < data.length; j++) {
let property = computeFlight(data[j]);
let entity={
id:modelAttribute.modelId,
name:modelName,
// 和时间轴关联
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
start: start,
stop: stop
})]),
position: property,
level: 'model',
// 根据所提供的速度计算模型的朝向
orientation: new Cesium.VelocityOrientationProperty(property),
// 模型数据
model: {
uri: modelAttribute.modelUrl,
},
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
};
//添加组
if(modelAttribute.isGroup){
if(modelAttribute.isGroup=='redGroup'){
entity.parent=group.redGroup;
}else {
entity.parent=group.blueGroup;
}
}
// 添加模型
viewer.entities.add(entity);
}
/**
* 计算飞行
*/
function computeFlight(source) {
// 取样位置 相当于一个集合
let property = new Cesium.SampledPositionProperty();
for (let i = 0; i < source.length; i++) {
let time = Cesium.JulianDate.addSeconds(start, source[i].time, new Cesium.JulianDate);
let position = Cesium.Cartesian3.fromDegrees(source[i].longitude, source[i].dimension, source[i].height + 5);
// 添加位置,和时间对应
property.addSample(time, position);
}
return property;
}
}
/*
*{*} value 是double类型
*/
function ZRotate(pick,value) {
if (Cesium.defined(pick)) {
let position = pick.id._position;
var time = viewer.clock.currentTime;
pick.currentPosition = position.getValue(time);
}
viewer.entities.getById(pick.id._id).orientation = Cesium.Transforms.headingPitchRollQuaternion(pick.currentPosition, new Cesium.HeadingPitchRoll(value, 0, 0));
}
/*
*type为平移类型
*/
function modelTranslation(type,pick) {
let position = viewer.entities.getById(pick.id._id).position._value;
var cartographic = Cesium.Cartographic.fromCartesian(position);
var longitude = Cesium.Math.toDegrees(cartographic.longitude);//经度值
var latitude = Cesium.Math.toDegrees(cartographic.latitude);//纬度值
var height = cartographic.height; //模型高度
let newPostion;
if (type == "left") {
newPostion = Cesium.Cartesian3.fromDegrees(longitude - 0.00001, latitude, height)
} else if (type == "right") {
newPostion = Cesium.Cartesian3.fromDegrees(longitude + 0.00001, latitude, height)
} else if (type == "front") {
newPostion = Cesium.Cartesian3.fromDegrees(longitude, latitude + 0.00001, height)
} else if (type == "back") {
newPostion = Cesium.Cartesian3.fromDegrees(longitude, latitude - 0.00001, height)
}
viewer.entities.getById(pick.id._id).position = newPostion;
}
/**
* 创建半球
* @param saturnPosition
*/
function createSaturn(saturnPosition) {
viewer.entities.add({
id: 'Saturn',
name: "Saturn",
position: saturnPosition,
ellipsoid: {
radii: new Cesium.Cartesian3(20.0, 20.0, 20.0),
maximumCone: Cesium.Math.PI_OVER_TWO,
material: Cesium.Color.BLUE.withAlpha(0.3),
outline: true,
},
});
}
/**
* 雷达扫描初始化方法
*/
function addRadarEntity(saturnPosition) {
var cartographic = Cesium.Cartographic.fromCartesian(saturnPosition);
var longitude = Cesium.Math.toDegrees(cartographic.longitude);//经度值
var latitude = Cesium.Math.toDegrees(cartographic.latitude);//纬度值
viewer.scene.globe.depthTestAgainstTerrain = true;
// 雷达扫描中心(三维空间坐标)
var geographySpace = new Cesium.Cartographic(Cesium.Math.toRadians(longitude), Cesium.Math.toRadians(latitude), 0);
// 扫描颜色
var scanColor = new Cesium.Color(1.0, 0.0, 0.0, 1);
// 持续时间 毫秒
var duration = 4000;
// 绘制平面雷达扫描线
addRadarScanPostStage(geographySpace, 20, scanColor, duration);
}
/*
*添加雷达扫描
*/
function addRadarScanPostStage(cartographicCenter, radius, scanColor, duration) {
var ScanSegmentShader =
"uniform sampler2D colorTexture;\n" +
"uniform sampler2D depthTexture;\n" +
"varying vec2 v_textureCoordinates;\n" +
"uniform vec4 u_scanCenterEC;\n" +
"uniform vec3 u_scanPlaneNormalEC;\n" +
"uniform vec3 u_scanLineNormalEC;\n" +
"uniform float u_radius;\n" +
"uniform vec4 u_scanColor;\n" +
"vec4 toEye(in vec2 uv, in float depth)\n" +
" {\n" +
" vec2 xy = vec2((uv.x * 2.0 - 1.0),(uv.y * 2.0 - 1.0));\n" +
" vec4 posInCamera =czm_inverseProjection * vec4(xy, depth, 1.0);\n" +
" posInCamera =posInCamera / posInCamera.w;\n" +
" return posInCamera;\n" +
" }\n" +
"bool isPointOnLineRight(in vec3 ptOnLine, in vec3 lineNormal, in vec3 testPt)\n" +
"{\n" +
"vec3 v01 = testPt - ptOnLine;\n" +
"normalize(v01);\n" +
"vec3 temp = cross(v01, lineNormal);\n" +
"float d = dot(temp, u_scanPlaneNormalEC);\n" +
"return d > 0.5;\n" +
"}\n" +
"vec3 pointProjectOnPlane(in vec3 planeNormal, in vec3 planeOrigin, in vec3 point)\n" +
"{\n" +
"vec3 v01 = point -planeOrigin;\n" +
"float d = dot(planeNormal, v01) ;\n" +
"return (point - planeNormal * d);\n" +
"}\n" +
"float distancePointToLine(in vec3 ptOnLine, in vec3 lineNormal, in vec3 testPt)\n" +
"{\n" +
"vec3 tempPt = pointProjectOnPlane(lineNormal, ptOnLine, testPt);\n" +
"return length(tempPt - ptOnLine);\n" +
"}\n" +
"float getDepth(in vec4 depth)\n" +
"{\n" +
"float z_window = czm_unpackDepth(depth);\n" +
"z_window = czm_reverseLogDepth(z_window);\n" +
"float n_range = czm_depthRange.near;\n" +
"float f_range = czm_depthRange.far;\n" +
"return (2.0 * z_window - n_range - f_range) / (f_range - n_range);\n" +
"}\n" +
"void main()\n" +
"{\n" +
"gl_FragColor = texture2D(colorTexture, v_textureCoordinates);\n" +
"float depth = getDepth( texture2D(depthTexture, v_textureCoordinates));\n" +
"vec4 viewPos = toEye(v_textureCoordinates, depth);\n" +
"vec3 prjOnPlane = pointProjectOnPlane(u_scanPlaneNormalEC.xyz, u_scanCenterEC.xyz, viewPos.xyz);\n" +
"float dis = length(prjOnPlane.xyz - u_scanCenterEC.xyz);\n" +
"float twou_radius = u_radius * 2.0;\n" +
"if(dis < u_radius)\n" +
"{\n" +
"float f0 = 1.0 -abs(u_radius - dis) / u_radius;\n" +
"f0 = pow(f0, 64.0);\n" +
"vec3 lineEndPt = vec3(u_scanCenterEC.xyz) + u_scanLineNormalEC * u_radius;\n" +
"float f = 0.0;\n" +
"if(isPointOnLineRight(u_scanCenterEC.xyz, u_scanLineNormalEC.xyz, prjOnPlane.xyz))\n" +
"{\n" +
"float dis1= length(prjOnPlane.xyz - lineEndPt);\n" +
"f = abs(twou_radius -dis1) / twou_radius;\n" +
"f = pow(f, 3.0);\n" +
"}\n" +
"gl_FragColor = mix(gl_FragColor, u_scanColor, f + f0);\n" +
"}\n" +
"}\n";
var _Cartesian3Center = Cesium.Cartographic.toCartesian(cartographicCenter);
var _Cartesian4Center = new Cesium.Cartesian4(_Cartesian3Center.x, _Cartesian3Center.y, _Cartesian3Center.z, 1);
var _CartographicCenter1 = new Cesium.Cartographic(cartographicCenter.longitude, cartographicCenter.latitude, cartographicCenter.height + 500);
var _Cartesian3Center1 = Cesium.Cartographic.toCartesian(_CartographicCenter1);
var _Cartesian4Center1 = new Cesium.Cartesian4(_Cartesian3Center1.x, _Cartesian3Center1.y, _Cartesian3Center1.z, 1);
var _CartographicCenter2 = new Cesium.Cartographic(cartographicCenter.longitude + Cesium.Math.toRadians(0.001), cartographicCenter.latitude, cartographicCenter.height);
var _Cartesian3Center2 = Cesium.Cartographic.toCartesian(_CartographicCenter2);
var _Cartesian4Center2 = new Cesium.Cartesian4(_Cartesian3Center2.x, _Cartesian3Center2.y, _Cartesian3Center2.z, 1);
var _RotateQ = new Cesium.Quaternion();
var _RotateM = new Cesium.Matrix3();
var _time = (new Date()).getTime();
var _scratchCartesian4Center = new Cesium.Cartesian4();
var _scratchCartesian4Center1 = new Cesium.Cartesian4();
var _scratchCartesian4Center2 = new Cesium.Cartesian4();
var _scratchCartesian3Normal = new Cesium.Cartesian3();
var _scratchCartesian3Normal1 = new Cesium.Cartesian3();
ScanPostStage = new Cesium.PostProcessStage({
fragmentShader: ScanSegmentShader,
uniforms: {
u_scanCenterEC: function () {
return Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
},
u_scanPlaneNormalEC: function () {
var temp = Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
var temp1 = Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center1, _scratchCartesian4Center1);
_scratchCartesian3Normal.x = temp1.x - temp.x;
_scratchCartesian3Normal.y = temp1.y - temp.y;
_scratchCartesian3Normal.z = temp1.z - temp.z;
Cesium.Cartesian3.normalize(_scratchCartesian3Normal, _scratchCartesian3Normal);
return _scratchCartesian3Normal;
},
u_radius: radius,
u_scanLineNormalEC: function () {
var temp = Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
var temp1 = Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center1, _scratchCartesian4Center1);
var temp2 = Cesium.Matrix4.multiplyByVector(viewer.camera._viewMatrix, _Cartesian4Center2, _scratchCartesian4Center2);
_scratchCartesian3Normal.x = temp1.x - temp.x;
_scratchCartesian3Normal.y = temp1.y - temp.y;
_scratchCartesian3Normal.z = temp1.z - temp.z;
Cesium.Cartesian3.normalize(_scratchCartesian3Normal, _scratchCartesian3Normal);
_scratchCartesian3Normal1.x = temp2.x - temp.x;
_scratchCartesian3Normal1.y = temp2.y - temp.y;
_scratchCartesian3Normal1.z = temp2.z - temp.z;
var tempTime = (((new Date()).getTime() - _time) % duration) / duration;
Cesium.Quaternion.fromAxisAngle(_scratchCartesian3Normal, tempTime * Cesium.Math.PI * 2, _RotateQ);
Cesium.Matrix3.fromQuaternion(_RotateQ, _RotateM);
Cesium.Matrix3.multiplyByVector(_RotateM, _scratchCartesian3Normal1, _scratchCartesian3Normal1);
Cesium.Cartesian3.normalize(_scratchCartesian3Normal1, _scratchCartesian3Normal1);
return _scratchCartesian3Normal1;
},
u_scanColor: scanColor
}
});
viewer.scene.postProcessStages.add(ScanPostStage);
}
/*
*起始位置,终点位置
*/
function createPolyLine(startPosition, endPosition) {
//添加移动轨迹
viewer.entities.add({
polyline: {
positions: [startPosition, endPosition],
width: 10,
material: new Cesium.PolylineOutlineMaterialProperty({
color: Cesium.Color.YELLOW,
outline: false,
}),
outline: false,
clampToGround: true,
},
});
}
引入turf.js
/*
*点的经纬度,圆心的经纬度
*/
function isInArea(pointLongitude,pointLatitude,circleLongitude,circleLatitude){
//turf画点
var point = turf.point([pointLongitude, pointLatitude]);
//turf画圆,半径为20米
let circle = turf.circle([circleLongitude, circleLatitude], 20 / 1000.0/1000.0,{ steps: 5, units: 'kilometers', options: {} });
//判断是否点在圆内
res = turf.booleanPointInPolygon(point, circle);
//结果
return res
}