learning_cesium/叠加天气图片.html

586 lines
23 KiB
HTML
Raw Normal View History

2024-03-19 18:06:25 +08:00
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Use correct character set. -->
<meta charset="utf-8" />
<!-- Tell IE to use the latest, best version. -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
<title>天气功能</title>
<!-- <script src="./Build168/Cesium/Cesium.js"></script> -->
<script src="./Build/Cesium/Cesium.js"></script>
<script src="./js/utils/mapUtil.js"></script>
<!-- 添加天地图的cesium的扩展插件目前支持cesuim1.52、1.58、1.63.1。 -->
<script src="http://api.tianditu.gov.cn/cdn/plugins/cesium/cesiumTdt.js"></script>
<script src="./js/CesiumPopup/CesiumPopup.js"></script>
<link href="./js/CesiumPopup/custompopup.css" rel="stylesheet" />
<style>
@import url(./Build/Cesium/Widgets/widgets.css);
html,
body,
#cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
#credit {
display: none;
}
#river-container {
position: absolute;
top: 100px;
left: 80px;
}
</style>
<!-- 引入样式 -->
<link rel="stylesheet" href="./js/elementui/index.css" />
<!-- import Vue before Element -->
<script src="./js/vue2710.js"></script>
<!-- import JavaScript -->
<script src="./js/elementui/index.js"></script>
</head>
<body>
<div id="app">
<div id="cesiumContainer"></div>
<div id="river-container">
<!-- <el-select v-model="value" placeholder="请选择" @change="selectRiver">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select> -->
<el-button @click="addCloudImage">云图</el-button>
<el-button @click="addRain">雨量</el-button>
</div>
<div id="credit"></div>
</div>
<script>
new Vue({
el: "#app",
data() {
return {
rainLevel: { 0: "小雨", 2.5: "小雨", 5: "小雨", 10: "中雨", 25: "大雨", 50: "暴雨", 100: "大暴雨", 250: "特大暴雨" },
addCloud: false,
options: [
{
value: "zhujiang",
label: "珠江流域片",
},
{
value: "dongnan",
label: "东南诸河片",
},
{
value: "xinan",
label: "西南诸河片",
},
{
value: "neiluhe",
label: "内陆河片",
},
{
value: "songliaohe",
label: "松辽河流域片",
},
{
value: "haihe",
label: "海河流域片",
},
{
value: "huaihe",
label: "淮河流域片",
},
{
value: "huanghe",
label: "黄河流域片",
},
{
value: "changjiang",
label: "长江流域片",
},
],
value: "",
cloudBound: [[70, 55], [140, 4]],//[左上角,右下角]百度未转换
};
},
methods: {
selectRiver(riverName) {
// this.addRiverGeojson(riverName);
this.addRiverWms(riverName);
},
addRiverWms(riverName) {
const wmsProvider = new Cesium.WebMapServiceImageryProvider({
// url: new Cesium.Resource({
// proxy: new Cesium.DefaultProxy("http://127.0.0.1:8888/proxy/"),
// url: "http://server.arcgisonline.com/arcgis/rest/services/Specialty/DeLorme_World_Base_Map/MapServer/WMSServer",
// url: "http://localhost:8088/geoserver/iot/wms",
url: "http://121.33.231.74:5097/geoserver/iot/wms",
// }),
layers: "iot:" + riverName + "_river",
crs: "4326",
rectangle: new Cesium.Rectangle(
Cesium.Math.toRadians(102.33435821533203),
Cesium.Math.toRadians(18.177719116210938),
Cesium.Math.toRadians(117.17308044433594),
Cesium.Math.toRadians(26.804235458374023)
),
// parameters对象可设置getMap请求中的参数
parameters: {
format: "image/png8",
transparent: true
}
});
viewer.imageryLayers.addImageryProvider(wmsProvider);
},
addRiverGeojson(riverName) {
let geoUrl =
"http://121.33.231.74:5097/geoserver/iot/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=iot%3A" + riverName + "_river&maxFeatures=999&outputFormat=application%2Fjson";
fetch(geoUrl)
.then((res) => res.json())
.then((result) => {
console.log(result)
let primitives = viewer.scene.primitives.add(
new Cesium.PrimitiveCollection()
);
primitives.show = false;
window.primitives = primitives;
result.features.forEach((feature) => {
this.addWaterFeature(primitives, feature);
});
// this.addWaterFeature(result.features[0]);
});
},
addWaterFeature(primitives, feature) {
let geometryType = feature.geometry.type;
let coord = feature.geometry.coordinates;
let geometryName = feature.geometry_name;
if (geometryType == "MultiPolygon") {
coord.forEach((polygon) => {
let outBoundary = null;
let holes = null;
// if(polygon.length==1){
outBoundary = new Cesium.PolygonHierarchy(
Cesium.Cartesian3.fromDegreesArray(polygon[0].flat(2))
);
// }
primitives.add(
new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.PolygonGeometry({
polygonHierarchy: outBoundary,
}),
attributes: {
// 通过attributes属性统一指定线段颜色
color: Cesium.ColorGeometryInstanceAttribute.fromColor(
new Cesium.Color(1.0, 0, 0, 1.0)
),
},
id: "面要素",
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
material: new Cesium.Material({
fabric: {
type: "Water",
uniforms: {
// 水的基本颜色
baseWaterColor: new Cesium.Color(
64 / 255.0,
157 / 255.0,
253 / 255.0,
0.5
),
// 水法向摄动的法线图
normalMap:
"./Build/Cesium/Assets/Textures/waterNormals.jpg",
// 波纹数量
frequency: 1000.0,
// 动画速度
animationSpeed: 0.002,
// 振动的幅度
amplitude: 150,
// 镜面反射的强度
specularIntensity: 1,
},
},
}),
faceForward: true,
}),
})
);
});
}
},
initViewer() {
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5ZjRjNTZkNC01NDYxLTRhMjQtOGEwZC1kZjA3YzQ5YTJlZDkiLCJpZCI6MjYwODQsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1ODcxOTMwODN9.prGsSKyAW_9Ow5zHYPhbm3LsQL-ApQw5-5PNJkDaHi8";
var token = "bf156eb3c72350d62b008dc8a4ae1016";
// 服务域名
var tdtUrl = "https://t{s}.tianditu.gov.cn/";
// 服务负载子域,天地图地图服务二级域名包括t0-t7可以随机选择使用如http://t2.tianditu.gov.cn/vec_c/wmts?tk=您的密钥
var subdomains = ["0", "1", "2", "3", "4", "5", "6", "7"];
/**
* Viewer对象
* 用于构建应用程序的基本小部件。它将所有标准的Cesium部件组合到一个可重用的包中。
* 小部件可以通过使用mixin来扩展来添加对各种应用程序有用的功能
*/
//Initialize the viewer widget with several custom options and mixins.
var viewer = new Cesium.Viewer("cesiumContainer", {
/**
* 场景模式,默认SceneMode.SCENE3D
* SceneMode:指定场景是3D/2D/2.5D,可选值:
* MORPHING在模式之间变形如3D转2D
* COLUMBUS_VIEW2.5D视角,地图会被平铺,高度为非零的对象被绘制在上面。
* SCENE2D:2D模式地图会被自顶向下正射投影
* SCENE3D3D模式一个传统的三维视角的全球。
*/
// // sceneMode : Cesium.SceneMode.COLUMBUS_VIEW,
// sceneMode: Cesium.SceneMode.SCENE3D,
// //指定椭球面提供地形或其他几何图形数据,
// terrainProvider: Cesium.createWorldTerrain(),
// //指定影像数据的数据源,该选项只有在baseLayerPicker设置为false时生效
// // imageryProvider : new Cesium.OpenStreetMapImageryProvider({
// // url : 'https://a.tile.openstreetmap.org/'
// // }),
// //设置背景,如果为false则星星/月亮/太阳都不会渲染
// // skyBox : new Cesium.SkyBox({
// // sources : {
// // positiveX : 'stars/100_BK.jpg',
// // negativeX : 'stars/100_BK.jpg',
// // positiveY : 'stars/100_BK.jpg',
// // negativeY : 'stars/100_BK.jpg',
// // positiveZ : 'stars/100_BK.jpg',
// // negativeZ : 'stars/100_BK.jpg'
// // }
// // }),
// // Show Columbus View map with Web Mercator projection
// mapProjection: new Cesium.WebMercatorProjection(),
// geocoder: false, //位置查找
// homeButton: false, //视图返回初始位置
// sceneModePicker: false, //视角选择器
// baseLayerPicker: false, //底图选择器
// navigationHelpButton: false, //导航帮助按钮
// animation: false, //动画控制器
// creditContainer: "credit", //版权显示,指定dom对象的id,再通过id样式可以隐藏CESIUM 版本图标
// timeline: false, //时间线
// fullscreenButton: false, //全屏控件
// vrButton: false,
// selectionIndicator: true,
// // infoBox:false
// // shouldAnimate:true
// scene3DOnly: true, //默认false若为true,所有几何体实例将仅会在3D模式中渲染(在GPU内存中)
});
viewer.imageryLayers.removeAll();
// 叠加影像服务
var imgMap = new Cesium.UrlTemplateImageryProvider({
url: tdtUrl + "DataServer?T=img_w&x={x}&y={y}&l={z}&tk=" + token,
subdomains: subdomains,
tilingScheme: new Cesium.WebMercatorTilingScheme(),
maximumLevel: 18,
});
viewer.imageryLayers.addImageryProvider(imgMap);
var ciaMap = new Cesium.UrlTemplateImageryProvider({
url: tdtUrl + "DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=" + token,
subdomains: subdomains,
tilingScheme: new Cesium.WebMercatorTilingScheme(),
maximumLevel: 18,
});
viewer.imageryLayers.addImageryProvider(ciaMap);
// 叠加国界服务
var iboMap = new Cesium.UrlTemplateImageryProvider({
url: tdtUrl + "DataServer?T=ibo_w&x={x}&y={y}&l={z}&tk=" + token,
subdomains: subdomains,
tilingScheme: new Cesium.WebMercatorTilingScheme(),
maximumLevel: 10,
});
viewer.imageryLayers.addImageryProvider(iboMap);
// 叠加地形服务
var terrainUrls = new Array();
for (var i = 0; i < subdomains.length; i++) {
var url =
tdtUrl.replace("{s}", subdomains[i]) +
"DataServer?T=elv_c&tk=" +
token;
terrainUrls.push(url);
}
var provider = new Cesium.GeoTerrainProvider({
urls: terrainUrls,
});
viewer.terrainProvider = provider;
// 将三维球定位到中国
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(
103.84,
31.15,
17850000
),
orientation: {
heading: Cesium.Math.toRadians(348.4202942851978),
pitch: Cesium.Math.toRadians(-89.74026687972041),
roll: Cesium.Math.toRadians(0),
},
complete: function callback() {
// 定位完成之后的回调函数
},
});
//Add basic drag and drop functionality
viewer.extend(Cesium.viewerDragDropMixin);
//Show a pop-up alert if we encounter an error when processing a dropped file
viewer.dropError.addEventListener(function (
dropHandler,
name,
error
) {
console.log(error);
window.alert(error);
});
window.viewer = viewer;
window.scene = viewer.scene;
// this.addCloudImage()
this.initEvent();
this.createModel("SampleData/models/GroundVehicle/GroundVehicle.glb",3000)
},
coorsConvert(x, y) {
let mars = mapZbConvert.baiduTomars({ x, y })
let wgs = mapZbConvert.transformGCJ2WGS(mars.y, mars.x);
return { x: wgs.lon, y: wgs.lat }
},
convertBound() {
let lt = this.coorsConvert(this.cloudBound[0][0], this.cloudBound[0][1]);
let rb = this.coorsConvert(this.cloudBound[1][0], this.cloudBound[1][1]);
this.cloudBound = [[lt.x, lt.y], [rb.x, rb.y]]
},
addCloudImage() {
// 方式一:采用图层的方式
// const singleTileLayer = new Cesium.SingleTileImageryProvider({
// url: "http://121.33.231.74:4430/stallite/20221213/202212130815.png",
// rectangle: Cesium.Rectangle.fromDegrees(this.cloudBound[0][0], this.cloudBound[1][1], this.cloudBound[1][0], this.cloudBound[0][1]),
// });
// viewer.imageryLayers.addImageryProvider(singleTileLayer);
// 方式二:采用实体面的方式
this.addCloud = !this.addCloud;
if (this.addCloud) {
var positions = [
Cesium.Cartesian3.fromDegrees(this.cloudBound[0][0], this.cloudBound[0][1]),
Cesium.Cartesian3.fromDegrees(this.cloudBound[1][0], this.cloudBound[0][1]),
Cesium.Cartesian3.fromDegrees(this.cloudBound[1][0], this.cloudBound[1][1]),
Cesium.Cartesian3.fromDegrees(this.cloudBound[0][0], this.cloudBound[1][1])
];
this.cloudEntity = viewer.entities.add({
show:false,
polygon: {
hierarchy: new Cesium.PolygonHierarchy(positions),
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
material: new Cesium.ImageMaterialProperty({
image: "http://121.33.231.74:4430/stallite/20221213/202212130000.png"
}),
// material:new Cesium.ColorMaterialProperty(Cesium.Color.TRANSPARENT)
}
});
// this.cloudEntity.show = false;
} else {
viewer.entities.remove(this.cloudEntity);
}
setTimeout(()=>{
// this.cloudEntity.polygon.material = new Cesium.ImageMaterialProperty({
// image: new Cesium.CallbackProperty(() => {
// return "http://121.33.231.74:4430/stallite/20221213/202212130000.png"
// },false)
// })
this.cloudEntity.show = true;
})
//方式三: 采用面geometry的方式
},
async addRain() {
const data = await fetch("./data/weather/raindata.json").then(res => res.json())
console.log(data)
data.content[0].location.forEach(item => {
let color = item.color.split(",");
let coords = item.latAndLong.reduce((res, item) => {
res.push([Number(item[1]), Number(item[0])]);
return res;
}, [])
// console.log("coords:",coords)
let cc = Cesium.Color.fromCssColorString("rgba(" + color[0] + "," + color[1] + "," + color[2] + ",0.5)");
// 创建primitive加载到场景中
scene.primitives.add(new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(
Cesium.Cartesian3.fromDegreesArray(coords.flat(3))
)
}),
attributes: {
// 通过attributes属性统一指定线段颜色
color: Cesium.ColorGeometryInstanceAttribute.fromColor(cc)
},
id: { ...item, "layer": "rain" }
}),
appearance: new Cesium.MaterialAppearance({
material: new Cesium.Material({
fabric: {
type: 'Color',
uniforms: {
color: cc
}
}
}),
faceForward: true
})
}));
})
},
createModel(url, height) {
viewer.entities.removeAll();
const position = Cesium.Cartesian3.fromDegrees(
-123.0744619,
44.0503706,
height
);
const heading = Cesium.Math.toRadians(135);
const pitch = 0;
const roll = 0;
const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
const orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
hpr
);
const entity = viewer.entities.add({
name: url,
position: position,
orientation: orientation,
model: {
uri: url,
minimumPixelSize: 128,
maximumScale: 20000,
},
});
// viewer.trackedEntity = entity;
},
/**
* 拾取API总结
* 1、camera.pickEllipsoid :返回一个椭球表面的点
* var cartesian3 = viewer.camera.pickEllipsoid(evt.position)
*
* 2、Globe.prototype.pick拾取带地形高度的地表坐标
* 使用 `Globe.prototype.pick` 方法。需要事先使用 `Camera.prototype.getPickRay` 创建射线。
* 接受一个必选的射线对象,一个必选的 `Scene` 对象,返回一个三维世界坐标 `Cartesian3`。
*
* // 从相机位置通过windowPosition 世界坐标中的像素创建一条射线。返回Cartesian3射线的位置和方向。
* let ray = viewer.camera.getPickRay(movement.position);
* // 查找射线与渲染的地球表面之间的交点。射线必须以世界坐标给出。返回Cartesian3对象
* position = viewer.scene.globe.pick(ray, viewer.scene);
*
* 3、scene.drillPick(evt.position)获取该点位置所有的Entity和Primitive
* 4、scene.pick(evt.position)获取该点位置最上层的Primitive
*
*
*/
initEvent() {
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
let vm = this;
handler.setInputAction(function (evt) {
// 隐藏气泡
let popups = document.getElementsByClassName("cesium-popup-bubble");
popups.length&&(popups[0].style.display='none')
// 获取该位置的所有primitive集合
let picks = viewer.scene.drillPick(evt.endPosition);
let pp = picks.filter(item => item.primitive instanceof Cesium.Primitive);
if (pp.length && pp[0].id) {
let item = pp.reduce((res,item)=>{
if(Number(item.id.symbol)>Number(res.symbol)){
res = item.id;
}
return res;
},pp[0].id);
// if(!item.layer||item.layer!="rain") return;
// let cartesian3 = viewer.scene.pickPosition(evt.position);
//捕获椭球体,将笛卡尔二维平面坐标转为椭球体的笛卡尔三维坐标,返回球体表面的点
var cartesian3 = viewer.camera.pickEllipsoid(evt.endPosition);
if (cartesian3) {
//将笛卡尔三维坐标转为地图坐标(弧度)
var cartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian3);
//将地图坐标(弧度)转为十进制的度数
var lat_String = Cesium.Math.toDegrees(cartographic.latitude).toFixed(4);
var log_String = Cesium.Math.toDegrees(cartographic.longitude).toFixed(4);
var alti_String = (viewer.camera.positionCartographic.height / 1000).toFixed(2);
vm.lng = log_String;
vm.lat = lat_String;
vm.alti = alti_String;
}
var html = "<div>" + (vm.rainLevel[item.symbol]) + "</div>";
// for(let key in fields){
// html += "<div>" + key + " :"+ fields[key] + "</div>"
// }
var a = new CesiumPopup({
// title: "详细信息框",
})
.setPosition(cartesian3)
.setHTML(html)
.addTo(viewer)
// a.on("close", function () {
// // console.log("close");
// });
// a.on("open", function () {
// // console.log("open");
// });
a.removeClass("cesium-popup-panel").addClassName("cesium-popup-bubble")
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
}
},
created() {
this.convertBound();
},
mounted() {
this.initViewer();
},
});
// 叠加水系
</script>
</body>
</html>