learning_cesium/叠加天气图片.html

586 lines
23 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>