Browse Source

时空数据预览

mork 2 months ago
parent
commit
ba2aa4ba11

+ 36 - 0
public/index.html

@@ -26,4 +26,40 @@
   <!-- built files will be auto injected -->
 </body>
 
+<style>
+    :root {
+      /* 滚动条整体部分,必须要设置 */
+      ::-webkit-scrollbar {
+        width: 6px;
+        height: 10px;
+        overflow-y: overlay;
+      }
+
+      /* 滚动条里面轨道,能向上向下移动 */
+      ::-webkit-scrollbar-track {
+        background-color: transparent;
+      }
+
+      /* 滚动条里面轨道,能向上向下移动 */
+      ::-webkit-scrollbar-track-piece {
+        background-color: transparent;
+      }
+
+      ::-webkit-scrollbar-thumb {
+        display: none;
+        border-radius: 6px;
+      }
+
+      /* 滚动条里面的小方块,能向上向下移动 */
+      *:hover::-webkit-scrollbar-thumb {
+        display: flex;
+        background-color: #808285;
+        border-radius: 6px;
+      }
+
+      *:hover::-webkit-scrollbar-track-piece {
+        background-color: #d1cfcf;;
+      }
+    }
+  </style>
 </html>

+ 3 - 0
public/static/config/config.js

@@ -14,6 +14,9 @@ let systemConfig = {
     // 引擎基础js
     scriptMain: "/static/plugins/skyscenery/SkyScenery.js",
 
+    GEOSERVER_URL_WMS: "http://121.43.55.7:8889/geoserver/kdyjs/wms",
+    GEOSERVER_URL_WFS: "http://121.43.55.7:8889/geoserver/kdyjs/wfs",
+    TDT_URL: "https://{s}.tianditu.gov.cn/",
     /* 以下为各模块定义各自全局变量的位置,包括 example 示例 */
     example: {
         scriptArr: [

BIN
public/static/images/point.png


BIN
public/static/images/u30.png


+ 2 - 0
src/components/AppVue/Footer.vue

@@ -16,5 +16,7 @@ export default {};
   height: 50px;
   line-height: 50px;
   margin: 0 auto;
+  position: absolute;
+  bottom: 90px;
 }
 </style>

+ 4 - 2
src/components/AppVue/Header.vue

@@ -46,10 +46,12 @@ export default {
           this.$router.push("/sksjgl");
           break;
         case 3:
-          this.$router.push("/application");
+          // this.$router.push("/application");
+          this.$router.push("/skmh/scene");
           break;
         case 4:
-          this.$router.push("/function");
+          // this.$router.push("/function");
+          this.$router.push("/wgn/sksj");
           break;
         case 5:
           this.$router.push("/wgn");

+ 7 - 1
src/router/index.js

@@ -58,7 +58,13 @@ const routes = [
         path: 'example',
         component: function () {
           return import('../views/skmh/Example.vue')
-        },
+        }
+      },
+      {
+        path: 'scene',
+        component: function () {
+          return import('../views/skmh/scene/index.vue')
+        }
       }
     ], // 子路由配置结束
   },

+ 110 - 0
src/views/skmh/scene/index.vue

@@ -0,0 +1,110 @@
+<template>
+    <div class="container">
+        <div style="padding: 20px;display: ruby-text;">
+            <div v-for="info in listData" :key="info" style="padding: 20px;">
+                <el-card style="border-radius: 10px !important;" @click="openVideo(info)">
+                    <div class="card picDiv"><img :src="info.img" ></div>
+                    <template #footer>
+                        <div style="width: 260px;">
+                            <div style="font-weight: bold;padding-bottom: 10px;">{{info.title}}</div>
+                            <div class="ellipsis3">
+                                <el-popover
+                                    title=""
+                                    width="300"
+                                    effect="dark"
+                                    :content="info.desc"
+                                    placement="top-start"
+                                >
+                                    <template #reference>
+                                        <div>{{info.desc}}</div>
+                                    </template>
+                                </el-popover>
+                            </div>
+                        </div>
+                    </template>
+                </el-card>
+            </div>
+        </div>
+        <div>
+            <el-dialog v-model="centerDialogVisible" title="预览" width="800" center :before-close="closeDialog">
+                <video :src="videoUrl" controls style="width: 100%;"/>  
+            </el-dialog>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: "",
+    data() {
+        return {
+            listData:[],
+            centerDialogVisible:false,
+            videoUrl:''
+
+        };
+    },
+    mounted() {
+        this.initData()
+    },
+    methods: {
+        initData(){
+            let that = this;
+            for(let i=0; i<10; i++){
+                let str = {
+                    url:"https://realbot-oss.oss-accelerate.aliyuncs.com/scrm/2025/2025-05-21/659fa31d-dc87-4882-8be5-1fba8fb7e6ff/flower.mp4",
+                    img:require("@static/images/u30.png"),
+                    title:"无人机实时成图_"+i,
+                    desc:"无人机巡察场景可实时接入无人机视频画面,叠加到GIS场景中,实现边飞边出图的真实场景还原,并可将历史画面内容实现快速切图、上图展示,利用AI技术赋能无人机场景,实现无人机视频画面目标提取,实现关键目标要素点位标记及相关业务分析应用,可用于城市规划、应急、军用侦察等行业应用场景。"
+                }
+                that.listData.push(str);
+            }
+        },
+        openVideo(param){
+            this.videoUrl = param.url;
+            this.centerDialogVisible=true
+        },
+        closeDialog(){
+            this.videoUrl='';
+            this.centerDialogVisible=false
+        }
+    }
+};
+</script>
+
+<style lang="less" scoped>
+/deep/ .el-card__body{
+    padding: 0px !important;
+    height: 140px;
+}
+.container {
+    width: 100%;
+    padding: 0px;
+    margin: 0 auto;
+}
+.card{
+    float: left;
+    height: 150px;
+    width: 300px;
+    cursor: pointer;
+    box-sizing: border-box;
+}
+.picDiv{
+    overflow: hidden;
+}
+.picDiv img{
+    width: 100%;
+    height: 100%;
+    transition: all 1s;
+}
+.picDiv img:hover{
+    transform:scale(1.2,1.2);
+}
+.ellipsis3{
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    -webkit-line-clamp: 3;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+</style>

+ 440 - 0
src/views/wgn/sksj/index.vue

@@ -0,0 +1,440 @@
+<template>
+    <div class="container">
+        <div style="position: absolute;top: 20px;left: 20px;z-index: 9;">
+            <div style="display: flex;">
+                <el-select
+                v-model="typeValue"
+                placeholder="Select"
+                style="width: 150px"
+                >
+                <el-option
+                    v-for="item in options"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                />
+                </el-select>
+                <el-input v-if="typeValue != 5" v-model="inputAddress" style="width: 200px;height: 32px;padding: 0px 10px;" placeholder="输入URL地址……" />
+                <div style="padding: 0px 10px;" v-if="typeValue == 5">
+                    <el-upload
+                        ref="uploadRef"
+                        action=""
+                        :auto-upload="false"
+                        :file-list="fileList"
+                        :show-file-list="false"
+                        accept=".json,.geojson"
+                        :on-change="handleChange"
+                    >
+                    <template #trigger>
+                        <el-button type="primary">上传文件</el-button>
+                    </template>
+                    </el-upload>
+                </div>
+                <el-button type="primary" @click="parse">解析</el-button>
+            </div>
+        </div>
+        <Map style="overflow: hidden;"></Map>
+        <div class="infoDialog" v-show="infoDialogShow">
+            <div class="close" @click="closeWin">×</div>
+            <div class="content" v-if="nowPoint != null">
+                <el-scrollbar>
+                    <div class="item" v-for="info in nowPointInfo" :key="info">{{info.key}}: {{ info.value }}</div>
+                </el-scrollbar>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import { ElMessage } from 'element-plus'
+import Map from "@/views/example/Map.vue";
+import { toRaw } from "vue";
+export default {
+    name: "",
+    components: {
+       Map
+    },
+    data() {
+        return {
+            listData:[],
+            fileList: [],
+            dataJson:[],
+            wmslayer: {},
+            pointImg:require('@static/images/point.png'),
+            geometryArr:[],
+            mapHandle:null,
+            infoDialogShow:false,
+            nowPoint: null,
+            nowPointInfo:null,
+            typeValue:'1',
+            inputAddress:'',
+            options:[
+                {
+                    value: '1',
+                    label: '栅格WMS服务',
+                },
+                {
+                    value: '2',
+                    label: '栅格WMTS服务',
+                },{
+                    value: '3',
+                    label: '栅格ArcGis服务',
+                },
+                {
+                    value: '4',
+                    label: '矢量服务',
+                },
+                {
+                    value: '5',
+                    label: '矢量文件',
+                }
+            ]
+        };
+    },
+    mounted() {
+        
+    },
+    methods: {
+        beforeUpload(file) {
+            const maxSize = 2; // 限制为2MB
+            if (file.size / 1024 / 1024 > maxSize) {
+                ElMessage({
+                    type: 'error',
+                    message: `文件大小不能超过 ${maxSize}MB!`,
+                })
+                return false;
+            }
+            return true;
+        },
+        handleChange(files,fileLists){
+            let that = this;
+            if (fileLists.length >1) {
+                fileLists.shift();
+            }
+            that.fileList = fileLists;
+            let reader = new FileReader();
+            reader.readAsText(that.fileList[0].raw, "UTF-8");
+            reader.onload = (evt) => {
+                that.dataJson = JSON.parse(evt.target.result);
+                console.log(that.dataJson); // 输出解析后的JSON数据
+                ElMessage({
+                    type: 'success',
+                    message: `文件处理成功,请解析上图展示`,
+                })
+            };
+        },
+        closeWin() {
+            this.infoDialogShow = false;
+            this.nowPoint = null;
+            this.nowPointInfo = null;
+        },
+        dwanMap(){
+            let that = this;
+            if(that.geometryArr.length>0){
+                that.geometryArr.map(function (info) {
+                    viewer.entities.remove(info)
+                })
+            }
+            that.geometryArr = that.dataJson.features.map(function (info) {
+                if(info.geometry.type == "Point"){
+                    return that.addPoint(info)
+                }else if(info.geometry.type == "LineString"){
+                    return that.addLine(info)
+                }else{
+                    return that.addPolygon(info)
+                }
+                
+            })
+            that.pointTCHandle();
+        },
+        addPolygon(param){
+            let arr = [];
+            param.geometry.coordinates.forEach(element => {
+                element.forEach(e => {
+                    arr.push(e[0]);
+                    arr.push(e[1]);
+                })
+            });
+            return viewer.entities.add(new SkyScenery.Entity({
+                name: " polygon",
+                polygon: {
+                    hierarchy: {
+                        positions: SkyScenery.Cartesian3.fromDegreesArray(arr)
+                    },
+                    heightReference: SkyScenery.HeightReference.CLAMP_TO_GROUND,
+                    material: SkyScenery.Color.CYAN.withAlpha(0.5)
+                },
+                info: {
+                    coor: [arr[0], arr[1]],
+                    properties: param.properties
+                },
+            }));
+        },
+        addLine(param){
+            return viewer.entities.add({
+                name: "line",
+                polyline: {
+                    //经纬度数组转世界坐标,带高度的话是fromDegreesArrayHeights
+                    positions: SkyScenery.Cartesian3.fromDegreesArray(param.geometry.coordinates),
+                    width: 2,
+                    material: SkyScenery.Color.CYAN,
+                    info: {
+                        properties: param.properties
+                    },
+                }
+            });
+        },
+        addPoint(param){
+            let that = this;
+            return viewer.entities.add(new SkyScenery.Entity({
+                name:"point",
+                position: SkyScenery.Cartesian3.fromDegrees(param.geometry.coordinates[0], param.geometry.coordinates[1]),
+                type: "point",
+                info: {
+                  coor: [param.geometry.coordinates[0], param.geometry.coordinates[1]],
+                  properties: param.properties
+                },
+                billboard: {
+                  image: that.pointImg,
+                  disableDepthTestDistance: Number.POSITIVE_INFINITY,
+                  scale: 0.3,
+                  horizontalOrigin: SkyScenery.HorizontalOrigin.CENTER,
+                  verticalOrigin: SkyScenery.VerticalOrigin.BOTTOM,
+                }
+              }));
+        },
+        // 点击事件绑定
+        pointTCHandle() {
+            let that = this;
+            if (!this.mapHandle) {
+                this.mapHandle = new SkyScenery.ScreenSpaceEventHandler(viewer.canvas, this);
+                this.mapHandle.setInputAction(function (movement) {
+                    that.infoDialogShow = false
+                    const pickedObject = viewer.scene.pick(movement.position);
+
+                    let cartesian = viewer.camera.pickEllipsoid(
+                        movement.position,
+                        viewer.scene.globe.ellipsoid
+                    );
+                    // 空间坐标转世界坐标(弧度)
+                    let cartographic = SkyScenery.Cartographic.fromCartesian(cartesian);
+                    // 弧度转为角度(经纬度)
+                    let lon = SkyScenery.Math.toDegrees(cartographic.longitude); // 经度值
+                    let lat = SkyScenery.Math.toDegrees(cartographic.latitude); // 纬度值
+                    let center = [lon,lat]
+                    if (SkyScenery.defined(pickedObject) && SkyScenery.defined(pickedObject.id)) {
+                        const entity = pickedObject.id;
+                        that.infoDialogShow = true
+                        that.nowPoint = entity.info;
+                        that.nowPointInfo =  Object.keys(that.nowPoint.properties).map(key => ({ key, value: that.nowPoint.properties[key] }));
+                        that.nowPoint["type"] = "info";
+                        // let xy = that.lonlatConvertToScreenXY(entity.info.coor)
+                        let xy = that.lonlatConvertToScreenXY(center)
+                        document.querySelector(".infoDialog").style.top = (xy.y - 230) + "px";
+                        document.querySelector(".infoDialog").style.left = (xy.x - 100) + "px";
+                    } else {
+                        // console.log('未拾取到实体');
+                    }
+                }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
+                viewer.scene.postRender.addEventListener(that.updatePosition, this);
+            } else {
+                toRaw(this.mapHandle).destroy();
+                this.mapHandle = null
+                that.nowPointInfo = null
+                viewer.scene.postRender.removeEventListener(that.updatePosition, this);
+            }
+        },
+        // 经纬度转屏幕坐标
+        lonlatConvertToScreenXY(lonlat) {
+            // 定义经纬度
+            var longitude = SkyScenery.Math.toRadians(lonlat[0]); // 例如:东经116.391度
+            var latitude = SkyScenery.Math.toRadians(lonlat[1]); // 例如:北纬39.907度
+            var height = 0; // 高度,通常在地表为0
+            // 将经纬度转换为笛卡尔坐标
+            // var cartographic = SkyScenery.Cartographic.fromDegrees(longitude, latitude, height);
+            var cartesian = SkyScenery.Cartesian3.fromRadians(longitude, latitude, height, viewer.scene.globe.ellipsoid);
+            // 将笛卡尔坐标转换为窗口坐标
+            var canvasCoordinates = viewer.scene.cartesianToCanvasCoordinates(cartesian);
+            return canvasCoordinates
+        },
+        // 位置更新
+        updatePosition() {
+            try {
+                if (this.nowPoint != null) {
+                    const obj = toRaw(this.nowPoint);
+                    let xy = this.lonlatConvertToScreenXY(obj.coor)
+                    if (!xy) {
+                        document.querySelector(".infoDialog").style.top = "-9999px";
+                        document.querySelector(".infoDialog").style.left = "-9999px";
+                    } else {
+                        document.querySelector(".infoDialog").style.top = (xy.y - 230) + "px";
+                        document.querySelector(".infoDialog").style.left = (xy.x - 100) + "px";
+                    }
+                }
+            } catch (error) {
+                // debugger
+            }
+        },
+        changBaseWMTS(){
+            let params = {layers: "WMTS-sksj",name:'WMTS-sksj',url:systemConfig.GEOSERVER_URL_WFS};
+            if(this.wmslayer[params.name]){
+                viewer.imageryLayers.remove(toRaw(this.wmslayer[params.name]))
+                 delete this.wmslayer[params.name];
+
+            }else{
+                let layer = viewer.imageryLayers.addImageryProvider(
+                    new SkyScenery.WebMapServiceImageryProvider({
+                        url: params.url,
+                        layers: params.layers,
+                        parameters: {
+                        TRANSPARENT: true,
+                        format: "image/png"
+                        }
+                    })
+                )
+                this.wmslayer[params.name] = layer;
+            }
+        },
+        addWMTSLayer(type) {
+            let matrixIds = [];
+            for (let i = 0; i < 19; i++) {
+                matrixIds[i] = i + 1;
+            }
+            console.log('[ WMTS ] >'+param)
+           viewer.imageryLayers.addImageryProvider(
+                new SkyScenery.WebMapTileServiceImageryProvider({
+                    url: systemConfig.TDT_URL + type + "_w/wmts?tk=f74e6c0cc247c42af05f7053e0b5fb9b",
+                    layer: type,
+                    style: "default",
+                    format: "tiles",
+                    // format:"image/png",
+                    tileMatrixSetID: "w",
+                    TileMatrixLabels: matrixIds,
+                    subdomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
+                    minimumLevel: 1,
+                    maximumLevel: 18,
+                    tilingScheme: new SkyScenery.WebMercatorTilingScheme()
+                })
+            );
+        },
+        addWMSLayer(param) {
+            console.log('[ WMS ] >'+param)
+            let url = param.url;
+            let layers = param.layers;
+            viewer.imageryLayers.addImageryProvider(
+                new SkyScenery.WebMapServiceImageryProvider({
+                    url: url,
+                    layers: layers,
+                    parameters: {
+                        TRANSPARENT: true,
+                        format: "image/png"
+                    }
+                })
+            );
+
+            // if (judge) {
+            //     let layer = viewer.imageryLayers.addImageryProvider(
+            //     new SkyScenery.WebMapServiceImageryProvider({
+            //         url: this.layerRoot,
+            //         layers: params.layers,
+            //         parameters: {
+            //         TRANSPARENT: true,
+            //         format: "image/png"
+            //         }
+            //     })
+            //     )
+            //     this.wmslayer[params.name] = layer;
+            // } else {
+            //     viewer.imageryLayers.remove(toRaw(this.wmslayer[params.name]))
+            //     delete this.wmslayer[params.name];
+            // }
+
+            
+        },
+        addARCGISLayer(param){
+            console.log('[ ArcGisMapServer ] >'+param)
+            // 添加地图服务
+            viewer.imageryLayers.addImageryProvider(
+                // 此处使用的地图服务地址也可存放在配置文件中
+                new SkyScenery.ArcGisMapServerImageryProvider({
+                    url: param.url
+                })
+            );
+        },
+        parse(){
+            console.log('[ eee ] >')
+            //  typeValue:'1',
+            // inputAddress:'',
+            let that = this;
+            if(that.typeValue == 1){
+                
+            }else if(that.typeValue == 2){
+             
+            }else if(that.typeValue == 3){
+                let param = {url:'https://service-api.onemap.sh.gov.cn/data-service-manage-service/MapProxyApi/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBsaWNhdGlvbl9pZCI6NjEsImFwcGxpY2F0aW9uX25hbWUiOiLpnZLmtabkuozkuInnu7TmnI3liqHns7vnu58iLCJleHAiOjIwNDY2Nzg0MDN9.IKUMdjUX4U1jncIUNren-iotL7duXI90aLECMjpvUX8/shmap_normal_web/MapServer'}
+                that.addARCGISLayer(param)
+            }else if(that.typeValue == 4){
+             
+            }else if(that.typeValue == 5){
+                //上传GeoJson文件解析数据并上图
+                if(this.mapHandle){
+                    toRaw(this.mapHandle).destroy();
+                    this.mapHandle = null
+                    that.nowPointInfo = null
+                }
+                that.closeWin()
+                that.dwanMap()
+                
+            }
+            
+        }
+    },
+    beforeDestroy() {
+        viewer = undefined
+    }
+};
+</script>
+<style lang="less" scoped>
+
+.container {
+    width: 100%;
+    padding: 0px;
+    margin: 0 auto;
+    overflow: hidden;
+}
+.infoDialog {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    max-width: 500px;
+    height: 200px;
+    // background: #01346f99;
+    background: #ffffff;
+    border-radius: 10px;
+
+    .close {
+      font-size: 24px;
+      position: absolute;
+      top: 6px;
+      right: 8px;
+      line-height: 24px;
+      width: 24px;
+      height: 24px;
+      cursor: pointer;
+      // color: #ffffff;
+      color: #000000;
+    }
+
+    .content {
+      height: 160px;
+      // color: #ffffff;
+      color: #000000;
+      margin: 30px 0px 10px 20px;
+      overflow: auto;
+      .item {
+        line-height: 30px;
+        margin-right: 20px;
+      }
+    }
+  }
+</style>