路径回放,视角跟随
- 使用GeoJson生成路径数据
- Cesium.DataSources加载
- 或取路径坐标信息
- 增加时间点间隔
<script>
import { onMounted, ref } from 'vue'
import * as Cesium from 'cesium'
export default {
name: "App",
setup() {
const cesiumContainer = ref();
onMounted(async () => {
if (cesiumContainer) {
viewer = new Cesium.Viewer(cesiumContainer.value, {
timeline: true, // 时间轴
animation: true, // 动画控件
});
viewer.scene.debugShowFramesPerSecond = true
//创建DataSource
var datasource = new Cesium.CustomDataSource("enetiestestdata");
viewer.dataSources.add(datasource)
let fileJson = await Cesium.GeoJsonDataSource.load('/src/assets/map.topojson');
viewer.dataSources.add(fileJson);
// 路径回放
let lujingdata = fileJson.entities.values[0].polyline.positions._value;
var property = new Cesium.SampledPositionProperty();
let starttime = new Date();
let stoptime;
let timestamp = starttime.getTime();
lujingdata.forEach((pos, index) => {
let time = new Date(timestamp + index * 5000);
stoptime = time;
property.addSample(Cesium.JulianDate.fromDate(time), pos);
})
property.setInterpolationOptions({
interpolationDegree: 0.0001,
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
});
var entitydd = datasource.entities.add({
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
start: Cesium.JulianDate.fromDate(starttime),
stop: Cesium.JulianDate.fromDate(new Date(stoptime))
})]),
position: property, // 点集
// billboard: {
// image: "./yingjiwuzi.png",
// scale: 0.5,
// pixelOffset: new Cesium.Cartesian2(0, -120),
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
// clampToGround: true //是否贴地
// },
model: {
uri: '/src/assets/xiaofangche.gltf',
scale: 1,
minimumPixelSize: 70,
maximumScale: 70
},
//朝向 定义模型朝向
orientation: new Cesium.VelocityOrientationProperty(property),
path: {
leadTime: 0,
resolution: 1,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.3,
color: Cesium.Color.GREEN
}),
width: 20
},
// 定义
label: {
text: "",
fillColor: Cesium.Color.RED,
pixelOffset:new Cesium.Cartesian2(0,-30)
},
});
viewer.clock.onTick.addEventListener((tick) => {
console.log(tick);
try {
entitydd.position.getValue(tick.currentTime);
// console.log(entitydd.position.getValue(tick.currentTime));
//转为经纬度
var cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(entitydd.position.getValue(tick.currentTime))
cartographic.longitude = Cesium.Math.toDegrees(cartographic.longitude)
cartographic.latitude = Cesium.Math.toDegrees(cartographic.latitude)
// console.log(cartographic);
entitydd.label.text = Number(cartographic.longitude).toFixed(4) + "," + Number(cartographic.latitude).toFixed(4);
} catch (error) {
console.error('-------------------------------------------',error);
}
})
// 视角跟踪,追随
viewer.trackedEntity =entitydd;
viewer.clock.currentTime = Cesium.JulianDate.fromDate(starttime); //修改时间轴的当前时间
viewer.clock.stopTime = Cesium.JulianDate.fromDate(new Date(stoptime));
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP,
viewer.clock.shouldAnimate = true; //开始播放
// viewer.zoomTo(fileJson)
}
})
return {
cesiumContainer
}
}
}
</script>
<!-- Clock的ClockRange属性
CLAMPED:达到终止时间后停止
LOOP_STOP:达到终止时间后重新循环
UNBOUNDED:达到终止时间后继续读秒(默认) -->
轨迹回放的主要思想是让模型的位置随时间来进行变换,并且让视角的中心一直跟着模型移动
- trackedEntity: 相机跟踪模型
- clock { multiplier: 控制播放速度 shouldAnimate: 设置是否移动 clockRange: 时间戳到终点后停止还是循环 }
- SampledPositionProperty: addSample() 用来构造时间和位置的关系 根据这个关系来移动模型和绘制路径
- sampleTerrainMostDetailed: 用来获取加载了地形后的真实坐标
- Cesium.CallbackProperty: 因为要绘制运动后的轨迹线,所以用回调的方式把走过的路径重新绘制
贴地线Ground
Entity方式贴地
let line = [105, 36, 116, 38, 118, 36]
viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray(line),//line要加载的线数据
width: 10,//线宽
clampToGround: true,//开启贴地
material: Cesium.Color.RED//颜色
}
});
//或者直接加载线数据地址,然后设置贴地即可
var promise = Cesium.GeoJsonDataSource.load(urlLine, {
clampToGround: true,//开启贴地
});
primitive方式贴地
Primitive方式贴地, 需要使用GroundPolylinePrimitive和GroundPolylineGeometry来创建Primitive与Geometry对象,而不是使用Primitive和PolylineGeometry创建Primitive与Geometry对象,代码如下:
viewer.scene.primitives.add(new Cesium.GroundPolylinePrimitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.GroundPolylineGeometry({
positions: Cesium.Cartesian3.fromDegreesArray(positions[i]),
width: 15.0,//线宽
vertexFormat: Cesium.PolylineColorAppearance.VERTEX_FORMAT
}),
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
new Cesium.Color.fromCssColorString("#0096ff")),
}
}),
appearance: new Cesium.PolylineColorAppearance({
translucent: false
})
}));
- Entity方式贴地更方便,但是效率不如primitive
水面效果
primitive
//1 创建 geometry
const polygon = new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(
Cesium.Cartesian3.fromDegreesArray(cixian.flat())
)
});
const geometry = Cesium.PolygonGeometry.createGeometry(polygon);
//2,创建geometryInstance
const instance = new Cesium.GeometryInstance({
geometry: geometry
});
//3,创建 material
var material = new Cesium.Material({
fabric: {
type: 'Water',
uniforms: {
baseWaterColor: new Cesium.Color( 0, 0, 0, 0.7),
normalMap: '/src/assets/waterNormals.jpg',
frequency: 20000,
animationSpeed: 0.1,
amplitude: 50,
specularIntensity: 0.5
}
}
})
// 4 创建Appearance
var appearance = new Cesium.EllipsoidSurfaceAppearance({
material: material,
})
// 5创建primitive
viewer.scene.primitives.add(new Cesium.Primitive({
id: 'idsss',
name: 'water_info',
asynchronous:false,
geometryInstances: instance,
appearance: appearance
}));
viewer.camera.setView({
destination:Cesium.Cartesian3.fromDegrees(114.28496124522002, 36.42363208436417,5000)
})
等高线
// 2、开启深度测试
viewer.scene.globe.enableLighting = true;
// 3、设置几个等高线必备的参数
var minHeight = -414.0; // 最小高度-例:最低接近死海高度
var maxHeight = 8777.0; // 最大高度-例:最高接近珠峰高度
var contourColor = Cesium.Color.RED.withAlpha(0.4); // 等高线的颜色
var contourSpacing = 200.0; // 等高线的等间距
var contourWidth = 1.0; // 等高线的宽度
淹没分析
/**
* 淹没分析函数,通过拉伸面的高度来进行分析
* @param {*} viewer
* @param {*} targertWaterHeight :目标水位高度
* @param {*} positions :研究区域底部坐标数组
* @param {*} waterHeight :当前水位高度
*/
let induationAnalysis = (viewer, targertWaterHeight, positions, waterHeight) => {
console.log('start................');
viewer.entities.add({
polygon: {
hierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(positions)),
perPositionHeight: true,
// 使用回调函数Callback,直接设置extrudedHeight会导致闪烁
extrudedHeight: new Cesium.CallbackProperty(function () {
waterHeight += 0.2;
console.log(waterHeight);
if (waterHeight > targertWaterHeight) {
waterHeight = targertWaterHeight;
}
return waterHeight;
}, false),
material: new Cesium.Color.fromBytes(64, 157, 253, 150),
}
});
}
const cesiumContainer = ref();
onMounted(() => {
if (cesiumContainer) {
viewer = new Cesium.Viewer(cesiumContainer.value, {
timeline: true, // 时间轴
animation: true, // 动画控件
terrainProvider: Cesium.createWorldTerrain({
requestVertexNormals: true, //开启地形光照
})
});
// 显示帧率
viewer.scene.debugShowFramesPerSecond = true
induationAnalysis(viewer, 5000, vdt.value.flat(), 30)
}
}
)
function setup() {
let viewer
//1.创建viewModel对象
const cesiumContainer = ref();
let subscribeLayerParameter = (name,mLayer,viewModel)=> {
//4.监听控件值的变化
Cesium.knockout.getObservable(viewModel, name).subscribe(function(value) {
//value值改变后会赋值给imagelayer的相应属性
console.log(name + ":" + value);
mLayer[name] = value;
});
}
onMounted(() => {
if (cesiumContainer) {
viewer = new Cesium.Viewer(cesiumContainer.value, {
//搜索框
geocoder: false,
//home键
homeButton: false,
// 动画控件
animation: false,
//全屏按钮
fullscreenButton: false,
//场景模式选择器
sceneModePicker: false,
//时间轴
timeline: false,
//导航提示
navigationHelpButton: false,
//地图选择器
baseLayerPicker: false,
terrainProvider: Cesium.createWorldTerrain({
requestVertexNormals: true, //开启地形光照
})
});
// 显示帧率
viewer.scene.debugShowFramesPerSecond = true
viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
url: "/src/assets/sjzTerrain/",
})
var elevationConterMaterial = new Cesium.Material({
fabric: {
type: 'ElevationContour',
uniforms: {
//等高线的颜色
color: new Cesium.Color(1.0, 0.0, 0.0, 1.0),
//等高线的间隔
spacing: 50,
width: 2,
}
}
});
viewer.scene.globe.material = elevationConterMaterial;
var viewModel = {
alpha: 1.0,
brightness: 1.0,
contrast: 1.0,
hue: 0.0,
saturation: 1.0,
gamma: 1.0
};
//2.监测viewModel中的属性
Cesium.knockout.track(viewModel);
//3.激活属性,将viewModel对象与html控件绑定
var toolBar = document.getElementById("toolbar");
Cesium.knockout.applyBindings(viewModel, toolBar);
//获取当前地球影像
var mLayer = viewer.imageryLayers.get(0);
subscribeLayerParameter("alpha",mLayer,viewModel);
subscribeLayerParameter("brightness",mLayer,viewModel);
subscribeLayerParameter("contrast",mLayer,viewModel);
subscribeLayerParameter("hue",mLayer,viewModel);
subscribeLayerParameter("saturation",mLayer,viewModel);
subscribeLayerParameter("gamma",mLayer,viewModel);
}
}
)
return {
cesiumContainer
}
}
地图等高线晕眩效果
var viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider: new Cesium.UrlTemplateImageryProvider({
url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
}),
terrainProvider: Cesium.createWorldTerrain({
requestVertexNormals: true,
requestWaterMask: true
})
});
viewer.camera.setView({
destination: new Cesium.Cartesian3(-2495709.521843174, -4391600.804712465, 3884463.7192916023),
orientation: {
heading: 1.7183056487769202,
pitch: -0.06460370548034144,
roll: 0.0079181631783527
}
});
// 开启光照
viewer.scene.globe.enableLighting = true;
// 创建一个拥有高程阴影和等高线的组合样式
function getElevationContourMaterial() {
return new Cesium.Material({
fabric: {
type: 'ElevationColorContour',
materials: {
contourMaterial: {
type: 'ElevationContour'
},
elevationRampMaterial: {
type: 'ElevationRamp'
}
},
components: {
diffuse: 'contourMaterial.alpha == 0.0 ? elevationRampMaterial.diffuse : contourMaterial.diffuse',
alpha: 'max(contourMaterial.alpha, elevationRampMaterial.alpha)'
}
},
translucent: false
});
}
var minHeight = -414.0; // 最低接近死海高度
var maxHeight = 8777.0; // 最高接近珠峰高度
var contourColor = Cesium.Color.RED.withAlpha(0.4); // 等高线的颜色
var contourSpacing = 150.0; // 等高线的等间距
var contourWidth = 1.0; // 等高线的宽度
// 1、高程阴影
// var material = Cesium.Material.fromType('ElevationRamp');
// var shadingUniforms = material.uniforms;
// shadingUniforms.minimumHeight = minHeight;
// shadingUniforms.maximumHeight = maxHeight;
// shadingUniforms.image = getColorRamp();
// 2、等高线
// var material = Cesium.Material.fromType('ElevationContour');
// var contourUniforms = material.uniforms;
// contourUniforms.width = contourWidth;
// contourUniforms.spacing = contourSpacing;
// contourUniforms.color = contourColor;
// 3、高程阴影+等高线
var material = getElevationContourMaterial();
var shadingUniforms = material.materials.elevationRampMaterial.uniforms;
shadingUniforms.minimumHeight = minHeight;
shadingUniforms.maximumHeight = maxHeight;
shadingUniforms.image = getColorRamp();
var contourUniforms = material.materials.contourMaterial.uniforms;
contourUniforms.width = contourWidth;
contourUniforms.spacing = contourSpacing;
contourUniforms.color = contourColor;
viewer.scene.globe.material = material;
function getColorRamp() {
var ramp = document.createElement('canvas');
ramp.width = 100;
ramp.height = 1;
var ctx = ramp.getContext('2d');
var values = [0.0, 0.045, 0.1, 0.15, 0.37, 0.54, 1.0];
var grd = ctx.createLinearGradient(0, 0, 100, 0);
grd.addColorStop(values[0], 'rgba(0,0,0,0.8)'); //black
grd.addColorStop(values[1], 'rgba(39,71,224,0.8)'); //blue
grd.addColorStop(values[2], 'rgba(211,59,125,0.8)'); //pink
grd.addColorStop(values[3], 'rgba(211,48,56,0.8)'); //red
grd.addColorStop(values[4], 'rgba(255,151,66,0.8)'); //orange
grd.addColorStop(values[5], 'rgba(255,215,0,0.8)'); //yellow
grd.addColorStop(values[6], 'rgba(255,255,255,0.8)'); //white
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 100, 1);
return ramp;
}