const { Cesium } = window; export default class LayerMgr { constructor() { // this.viewer = viewer } //加载模型 getGltf(viewer) { viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(114.97, 31.47,250), model: { uri: `${process.env.PUBLIC_URL}/models/dam/scene.gltf` , scale: 10, runAnimations: false }, }); } getWater(viewer) { const positions = [ 114.96554141845703, 31.487516479492188, 114.993221862792957, 31.487516479492188, 114.993221862792957, 31.4622646484375, 114.96554141845703, 31.4622646484375, ] let initialHeight = 120 const geometry = new Cesium.PolygonGeometry({ polygonHierarchy: new Cesium.PolygonHierarchy( Cesium.Cartesian3.fromDegreesArray(positions) ), extrudedHeight: initialHeight, perPositionHeight:false, }); const waterPrimitive = new Cesium.Primitive({ geometryInstances: new Cesium.GeometryInstance({ geometry }), appearance: new Cesium.EllipsoidSurfaceAppearance({ aboveGround: true, material: new Cesium.Material({ fabric: { type: 'Water', uniforms: { normalMap: Cesium.buildModuleUrl( `${process.env.PUBLIC_URL}/models/waternormals.jpg` ), frequency: 1000.0, animationSpeed: 0.01, amplitude: 10, }, }, }), }), show: true, // releaseGeometryInstances: false }); viewer.scene.primitives.add(waterPrimitive); // 自动抬升 let height = 0; setInterval(() => { if (height < 0.4) { height += 0.001; // height += 0.02; // waterPrimitive.extrudedHeight = height; // 触发setter var currentModelMatrix = Cesium.Matrix4.clone(waterPrimitive.modelMatrix); // 定义平移向量(例如,沿x轴平移100单位) var translation = new Cesium.Cartesian3(-height*0.7, height, height*0.8); // 创建一个平移矩阵 var translationMatrix = Cesium.Matrix4.fromTranslation(translation); // 计算新的modelMatrix(将平移矩阵应用到当前模型矩阵上) var newModelMatrix = Cesium.Matrix4.multiply(translationMatrix, currentModelMatrix, new Cesium.Matrix4()); waterPrimitive.modelMatrix = newModelMatrix; } }, 100); } getWater2(viewer) { // const waterSurface = viewer.entities.add({ // rectangle: { // coordinates: Cesium.Rectangle.fromDegrees(114.9, 31.4, 115.9, 32.4), // material: new Cesium.WaterMaterial({ // normalMapUrl: `${process.env.PUBLIC_URL}/models/waternormals.jpg`, // 水波纹法线贴图 // frequency: 1000.0, // 波纹密度 // animationSpeed: 0.05, // 波动速度 // amplitude: 5.0 // 波高 // }), // height: 130.0 // 水面高度(可动态调整) // } // }); } async getQxsy(viewer) { try { let tileset = await Cesium.Cesium3DTileset.fromUrl( 'http://res3d.oss-cn-shenzhen.aliyuncs.com/macheng/xiaoyutan/Scene/3DTILE.json', { maximumScreenSpaceError: 1, //精细程度越小越精细 maximumMemoryUsage: 1000, //不可设置太高,目标机子空闲内存值以内,防止浏览器过于卡 } ); viewer.scene.primitives.add(tileset); const offsetHeight = 15 const boundingSphere = tileset.boundingSphere const cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center) const surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0) const offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, offsetHeight) const translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3()) tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation) viewer.flyTo(tileset) } catch (error) { console.error(`Error creating tileset: ${error}`); } // fetch(`${process.env.PUBLIC_URL}/data/geojson/macheng/boua.geojson`) // .then(resp => resp.json()) // .then(data => { // let features = data.features; // let positionArray = []; // // 获取区域的经纬度坐标 // for (let i = 0; i < features[0].geometry.coordinates[0].length; i++) { // let coor = features[0].geometry.coordinates[0][i]; // positionArray.push(coor[0]); // positionArray.push(coor[1]); // } // // 遮罩 // let polygonEntity = new Cesium.Entity({ // polygon: { // hierarchy: { // // 添加外部区域为1/4半圆,设置为180会报错 [0, 0, 0, 90, 179, 90, 179, 0] // positions: Cesium.Cartesian3.fromDegreesArray([100, 0, 100, 89, 150, 89, 150, 0]), // // 中心挖空的“洞” // holes: [{ // positions: Cesium.Cartesian3.fromDegreesArray(positionArray) // }] // }, // material: Cesium.Color.BLACK.withAlpha(0.7) //new Cesium.Color(236,242,249, 1) // } // }); // // 边界线 // let lineEntity = new Cesium.Entity({ // polyline: { // positions: Cesium.Cartesian3.fromDegreesArray(positionArray), // width: 7, // material: Cesium.Color.fromCssColorString('#7AE3C8'),//边界线颜色//Cesium.Color.YELLOW //new Cesium.Color(122,227,200, 1) // clampToGround: true, // zIndex: 10 // } // }); // viewer.entities.add(polygonEntity); // viewer.entities.add(lineEntity); // //viewer.flyTo(lineEntity); // }); // tileset.readyPromise.then(function () { // viewer.zoomTo( // tileset, // new Cesium.HeadingPitchRange( // 0, // -0.7, // 2500 // // tileset.boundingSphere.radius * 10 // ) // ); // }); //设置倾斜摄影Z轴高度 // tileset.readyPromise.then(function (tileset) { // const offsetHeight = 15 // const boundingSphere = tileset.boundingSphere // const cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center) // const surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0) // const offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, offsetHeight) // const translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3()) // tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation) // // viewer.flyTo(tileset) // }) } async getDem(viewer) { const terrainProvider = await Cesium.CesiumTerrainProvider.fromUrl( // "/shzh/mapres/terrain", // `${process.env.PUBLIC_URL}/terrain`, // "http://192.168.66.51:42225/distribution/terrain/5vjnbauc3frn", "https://map1.oss-cn-shenzhen.aliyuncs.com/tsg/terrain2", { requestVertexNormals: true }) viewer.terrainProvider = terrainProvider } async getWxyx(viewer) { const tiandiKey = "efc861f25f96dc6e5f884f0403ebfefd"; //天地图key,官网申请 const baseUrl = "https://{s}.tianditu.gov.cn";//'https://t{0-7}.tianditu.gov.cn'; const imageryProvider = new Cesium.UrlTemplateImageryProvider({ //url: `http://res3dstatic{s}.cloudowr.cn/${localStorage.getItem('address')}/dom2/{z}/{x}/{y}.png`, url: baseUrl + '/DataServer?T=img_w&x={x}&y={y}&l={z}&tk='+tiandiKey, subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'], //minimumLevel:10, maximumLevel: 17, }) viewer.imageryLayers.addImageryProvider(imageryProvider); } getRlt(viewer) { function getColorRamp() { const ramp = document.createElement("canvas"); ramp.width = 100; ramp.height = 1; const ctx = ramp.getContext("2d"); let values; values = [0.0, 0.045, 0.1, 0.15, 0.37, 0.54, 1.0]; const grd = ctx.createLinearGradient(0, 0, 100, 0); grd.addColorStop(values[0], "#000000"); //black grd.addColorStop(values[1], "#2747E0"); //blue grd.addColorStop(values[2], "#D33B7D"); //pink grd.addColorStop(values[3], "#D33038"); //red grd.addColorStop(values[4], "#FF9742"); //orange grd.addColorStop(values[5], "#ffd700"); //yellow grd.addColorStop(values[6], "#ffffff"); //white ctx.fillStyle = grd; ctx.fillRect(0, 0, 100, 1); return ramp; } const minHeight = -414.0; // approximate dead sea elevation const maxHeight = 8777.0; // approximate everest elevation let shadingUniforms = {}; function updateMaterial() { // const globe = viewer.scene.globe; // let material; // material = Cesium.Material.fromType("ElevationRamp"); // shadingUniforms = material.uniforms; // shadingUniforms.minimumHeight = minHeight; // shadingUniforms.maximumHeight = maxHeight; // shadingUniforms.image = getColorRamp(); // globe.material = material; const material = Cesium.Material.fromType("ElevationRamp") material.uniforms.image = getColorRamp() viewer.scene.globe.material = material } updateMaterial(); } getRlt2(viewer) { const gridData = { minLon: 110.0, // 最小经度 minLat: 30.0, // 最小纬度 deltaLon: 0.1, // 经度间隔 deltaLat: 0.1, // 纬度间隔 rows: 10, // 行数(纬度方向) cols: 10, // 列数(经度方向) heights: [ // 高度值数组(行优先存储) /* 10x10 网格高度值 */ 100, 120, 140, 140,135,130,120,110,100,90, 100, 120, 140, 140,135,130,120,110,100,90, 100, 120, 140, 140,135,130,120,110,100,90, 100, 120, 140, 140,135,130,120,110,100,90, 100, 120, 140, 140,135,130,120,110,100,90, 100, 120, 140, 140,135,130,120,110,100,90, 100, 120, 140, 140,135,130,120,110,100,90, 100, 120, 140, 140,135,130,120,110,100,90, 100, 120, 140, 140,135,130,120,110,100,90, 100, 120, 140, 140,135,130,120,110,100,90, // ... 共 100 个值 ] }; // 2. 创建颜色映射函数(根据高度返回颜色) function heightToColor(height) { // 示例:根据高度值返回渐变色 const minH = 100, maxH = 500; const ratio = Math.min(1, Math.max(0, (height - minH) / (maxH - minH))); // 蓝 -> 绿 -> 红 渐变 const r = Math.floor(255 * ratio); const g = Math.floor(255 * (1 - ratio)); const b = 128; return new Cesium.Color(r / 255, g / 255, b / 255, 1.0); } // 3. 生成网格几何数据 function createGridGeometry(grid) { const positions = []; const colors = []; const indices = []; let vertexIndex = 0; for (let row = 0; row < grid.rows; row++) { for (let col = 0; col < grid.cols; col++) { // 计算当前网格点经纬度 const lon = grid.minLon + col * grid.deltaLon; const lat = grid.minLat + row * grid.deltaLat; const height = grid.heights[row * grid.cols + col]; // 将经纬度转换为笛卡尔坐标 const position = Cesium.Cartesian3.fromDegrees(lon, lat, height); positions.push(position); // 计算颜色 const color = heightToColor(height); colors.push(color.red, color.green, color.blue, color.alpha); // 生成三角形索引(跳过边界) if (row < grid.rows - 1 && col < grid.cols - 1) { const topLeft = vertexIndex; const topRight = topLeft + 1; const bottomLeft = topLeft + grid.cols; const bottomRight = bottomLeft + 1; // 两个三角形组成一个网格单元 indices.push(topLeft, bottomLeft, topRight); indices.push(topRight, bottomLeft, bottomRight); } vertexIndex++; } } return { positions, colors, indices }; } // 4. 创建Primitive并添加到场景 function createGridPrimitive(geometry) { const appearance = new Cesium.PerInstanceColorAppearance({ flat: true, // 平面着色 renderState: { depthTest: { enabled: true } // 启用深度测试 } }); const primitive = new Cesium.Primitive({ geometryInstances: new Cesium.GeometryInstance({ geometry: new Cesium.PolygonGeometry({ polygonHierarchy: new Cesium.PolygonHierarchy(geometry.positions), vertexFormat: appearance.vertexFormat }), attributes: { color: new Cesium.ColorGeometryInstanceAttribute.fromColor( new Cesium.Color(1.0, 1.0, 1.0, 1.0) ) } }), appearance: appearance }); viewer.scene.primitives.add(primitive); return primitive; } const geometryData = createGridGeometry(gridData); const gridPrimitive = createGridPrimitive(geometryData); } async getRlt3(viewer) { // const gridData = { // minLon: 110.0, // 最小经度 // minLat: 30.0, // 最小纬度 // deltaLon: 0.1, // 经度间隔 // deltaLat: 0.1, // 纬度间隔 // maxLon: 110.0 + 10 * 0.1, // minLon + cols * deltaLon // maxLat: 30.0 + 10 * 0.1, // minLat + rows * deltaLat // rows: 10, // 行数(纬度方向) // cols: 10, // 列数(经度方向) // // heights: [ // 高度值数组(行优先存储) // // /* 10x10 网格高度值 */ // // 100, 120, 140, ..., // // 110, 130, 150, ..., // // // ... 共 100 个值 // // ] // }; // // 2. 创建颜色映射函数(根据高度返回颜色) // function heightToColor(height) { // // 示例:根据高度值返回渐变色 // const minH = 1, maxH = 300; // const ratio = Math.min(1, Math.max(0, (height - minH) / (maxH - minH))); // // 蓝 -> 绿 -> 红 渐变 // const r = Math.floor(255 * ratio); // const g = Math.floor(255 * (1 - ratio)); // const b = 128; // // return new Cesium.Color(r / 255, g / 255, b / 255, 1.0); // return [r,g,b,100] // } const gridData = { minLon: 110.0, // 最小经度 minLat: 30.0, // 最小纬度 deltaLon: 0.01, // 经度间隔 deltaLat: 0.01, // 纬度间隔 maxLon: 110.0 + 100 * 0.01, // minLon + cols * deltaLon maxLat: 30.0 + 100 * 0.01, // minLat + rows * deltaLat rows: 100, // 行数(纬度方向) cols: 100, // 列数(经度方向) cccc:[ [10,10,10,10,10,10,10,10,10,10], [10,10,10,10,10,10,10,10,10,10], [10,10,10,10,10,10,10,10,10,10], [10,10,10,10,10,10,10,10,10,10], [10,10,10,10,200,10,10,10,10,10], [10,10,10,10,10,10,10,10,10,10], [10,10,10,10,10,10,10,10,10,10], [10,10,10,10,10,10,10,10,10,10], [10,10,10,10,10,10,10,10,10,10], [10,10,10,10,10,10,10,10,10,10], ] }; // 2. 创建颜色映射函数(根据高度返回颜色) function heightToColor(height) { // 示例:根据高度值返回渐变色 const minH = 1, maxH = 300; const ratio = Math.min(1, Math.max(0, (height - minH) / (maxH - minH))); // 蓝 -> 绿 -> 红 渐变 const r = Math.floor(255 * ratio); const g = Math.floor(255 * (1 - ratio)); const b = 128; // return new Cesium.Color(r / 255, g / 255, b / 255, 1.0); return [r,g,b,100] } for (let index = 0; index<10; index++){ const canvas = document.createElement('canvas'); canvas.width = gridData.cols; // 每个网格一个像素 canvas.height = gridData.rows; const context = canvas.getContext('2d'); for (let row = 0; row < gridData.rows; row++) { for (let col = 0; col < gridData.cols; col++) { const color = heightToColor(col*index*0.5); // const color = heightToColor(gridData.cccc[row][col]); const style = `rgba(${color[0]}, ${color[1]}, ${color[2]}, ${50})`; context.fillStyle = style; context.fillRect(col, row, 1, 1); // 每个像素一个网格点 } } const imageUrl = canvas.toDataURL('image/png'); // 5. 创建矩形范围(覆盖整个网格) const rectangle = Cesium.Rectangle.fromDegrees( gridData.minLon, gridData.minLat, gridData.maxLon, gridData.maxLat ); // 6. 创建SingleTileImageryProvider const imageryProvider = new Cesium.SingleTileImageryProvider({ url: imageUrl, rectangle: rectangle }); // 7. 添加到影像层集合 viewer.imageryLayers.addImageryProvider(imageryProvider); await this.sleep(1000) } } async sleep(time) { await new Promise(resolve => setTimeout(resolve, time)); } getCzmlData(){ const gridData = { minLon: 110.0, // 最小经度 minLat: 30.0, // 最小纬度 deltaLon: 0.1, // 经度间隔 deltaLat: 0.1, // 纬度间隔 rows: 10, // 行数(纬度方向) cols: 10, // 列数(经度方向) // heights: [ // 高度值数组(行优先存储) // /* 10x10 网格高度值 */ // 100, 120, 140, ..., // 110, 130, 150, ..., // // ... 共 100 个值 // ] }; // 2. 创建颜色映射函数(根据高度返回颜色) function heightToColor(height) { // 示例:根据高度值返回渐变色 const minH = 1, maxH = 300; const ratio = Math.min(1, Math.max(0, (height - minH) / (maxH - minH))); // 蓝 -> 绿 -> 红 渐变 const r = Math.floor(255 * ratio); const g = Math.floor(255 * (1 - ratio)); const b = 128; // return new Cesium.Color(r / 255, g / 255, b / 255, 1.0); return [r,g,b,100] } // 3. 生成网格几何数据1帧 function createGridGeometry(grid,ccc) { const positions = []; const colors = []; const indices = []; let vertexIndex = 0; for (let row = 0; row < grid.rows; row++) { for (let col = 0; col < grid.cols; col++) { // 计算当前网格点经纬度 const lon = grid.minLon + col * grid.deltaLon; const lat = grid.minLat + row * grid.deltaLat; const height = row+col+2; const color = heightToColor(height*ccc*2); // const color = heightToColor(height*ccc*0.1); positions.push([ [lon-grid.deltaLon/2,lat,ccc===row?4000:3000],//左上 [lon+grid.deltaLon/2,lat,ccc===row?4000:3000],//右上 [lon,lat+grid.deltaLat,(ccc===(row+1))?4000:3000],//左下 color,//颜色 ]) positions.push([ [lon+grid.deltaLon,lat+grid.deltaLat,(ccc===(row+1))?4000:3000],//左下 [lon,lat+grid.deltaLat,(ccc===(row+1))?4000:3000],//右下 [lon+grid.deltaLon/2,lat,ccc===row?4000:3000],//右上 color,//颜色 ]) // 将经纬度转换为笛卡尔坐标 // const position = Cesium.Cartesian3.fromDegrees(lon, lat, height); // 计算颜色 // const color = heightToColor(height); colors.push(color.red, color.green, color.blue, color.alpha); // positions.push([lon,lat,height,[color.red,color.green,color.blue,color.alpha]]); // 生成三角形索引(跳过边界) if (row < grid.rows - 1 && col < grid.cols - 1) { const topLeft = vertexIndex; const topRight = topLeft + 1; const bottomLeft = topLeft + grid.cols; const bottomRight = bottomLeft + 1; // 两个三角形组成一个网格单元 indices.push(topLeft, bottomLeft, topRight); indices.push(topRight, bottomLeft, bottomRight); } vertexIndex++; } } return positions; } const alllist = [] for (let index = 0; index<10; index++){ alllist.push(createGridGeometry(gridData,index+1)) } return alllist } async getCzml(viewer) { const gridData = { minLon: 110.0, // 最小经度 minLat: 30.0, // 最小纬度 deltaLon: 0.1, // 经度间隔 deltaLat: 0.1, // 纬度间隔 rows: 10, // 行数(纬度方向) cols: 10, // 列数(经度方向) // heights: [ // 高度值数组(行优先存储) // /* 10x10 网格高度值 */ // 100, 120, 140, ..., // 110, 130, 150, ..., // // ... 共 100 个值 // ] }; // 2. 创建颜色映射函数(根据高度返回颜色) function heightToColor(height) { // 示例:根据高度值返回渐变色 const minH = 1, maxH = 300; const ratio = Math.min(1, Math.max(0, (height - minH) / (maxH - minH))); // 蓝 -> 绿 -> 红 渐变 const r = Math.floor(255 * ratio); const g = Math.floor(255 * (1 - ratio)); const b = 128; // return new Cesium.Color(r / 255, g / 255, b / 255, 1.0); return [r,g,b,100] } // 3. 生成网格几何数据1帧 function createGridGeometry(grid,ccc) { const positions = []; const colors = []; const indices = []; let vertexIndex = 0; for (let row = 0; row < grid.rows; row++) { for (let col = 0; col < grid.cols; col++) { // 计算当前网格点经纬度 const lon = grid.minLon + col * grid.deltaLon; const lat = grid.minLat + row * grid.deltaLat; const height = row+col+2; const color = heightToColor(height*ccc*2); // const color = heightToColor(height*ccc*0.1); positions.push([ [lon-grid.deltaLon/2,lat,ccc===row?7000:3000],//左上 [lon+grid.deltaLon/2,lat,ccc===row?7000:3000],//右上 [lon,lat+grid.deltaLat,(ccc===(row+1))?7000:3000],//左下 color,//颜色 ]) positions.push([ [lon+grid.deltaLon,lat+grid.deltaLat,(ccc===(row+1))?7000:3000],//左下 [lon,lat+grid.deltaLat,(ccc===(row+1))?7000:3000],//右下 [lon+grid.deltaLon/2,lat,ccc===row?7000:3000],//右上 color,//颜色 ]) // 将经纬度转换为笛卡尔坐标 // const position = Cesium.Cartesian3.fromDegrees(lon, lat, height); // 计算颜色 // const color = heightToColor(height); colors.push(color.red, color.green, color.blue, color.alpha); // positions.push([lon,lat,height,[color.red,color.green,color.blue,color.alpha]]); // 生成三角形索引(跳过边界) if (row < grid.rows - 1 && col < grid.cols - 1) { const topLeft = vertexIndex; const topRight = topLeft + 1; const bottomLeft = topLeft + grid.cols; const bottomRight = bottomLeft + 1; // 两个三角形组成一个网格单元 indices.push(topLeft, bottomLeft, topRight); indices.push(topRight, bottomLeft, bottomRight); } vertexIndex++; } } return positions; } // const geometryData = createGridGeometry(gridData,1); const alllist = [] for (let index = 0; index<1; index++){ alllist.push(createGridGeometry(gridData,index+1)) } const czmls = [] alllist.map((item,index)=>{ //时间维度 const czml = [{ id: "document", name: "CZML Colors", version: "1.0", }] item.map((item2,index2)=>{ czml.push({ id: "rgba"+index2, name: "Rectangle with outline using RGBA Colors", polygon: { positions: { cartographicDegrees: [ ...item2[0], ...item2[1], ...item2[2], ], }, // material: { // solidColor: { // color: { // rgba: item2[3], // }, // }, // }, material: { image: { image: { uri: Cesium.buildModuleUrl( `${process.env.PUBLIC_URL}/models/waternormals.jpg` ) }, // color: { // rgba: [255, 255, 255, 128], // }, }, }, extrudedHeight: 0, perPositionHeight: true, }, }) }) czmls.push(czml) }) // let dataSourcePromise = null; for (const item of czmls) { // if(dataSourcePromise){ // viewer.dataSources.remove(dataSourcePromise); // dataSourcePromise = null // } const dataSourcePromise = await Cesium.CzmlDataSource.load(item) viewer.dataSources.add(dataSourcePromise); // setTimeout(() => { // viewer.dataSources.remove(dataSourcePromise); // }, 1000); await this.sleep(1000) } } }