使用OpenLayer+Vue实现地图影像加载功能,带图层切换

<template>
    <div>
        <!-- 地图容器 -->
        <div id='rtsmap' class="rtsmap" ref="rtsmap"></div>

        <!-- 悬浮按钮组、非领导不需要ksh按钮 -->
        <div class="rop_div">
            <!-- 图层管理 -->
            <div class="rop_item_div" id="tc_btn" v-on:click="openLy">
                <img :src="tcMbTogget ? require('@/assets/tc_xz.png') : require('@/assets/tc.png')" class="rop_item_img" />
            </div>
            <!-- 属性查询 -->
            <div class="rop_item_div" id="sx_btn" v-on:click="openSxLy">
                <img :src="sxGnTogget ? require('@/assets/cx_xz.png') : require('@/assets/cx.png')" class="rop_item_img" />
            </div>
            <!-- 可视化开关 -->
            <div class="rop_item_div" id="ksh_btn" v-on:click="openKshLy">
                <img :src="tjGnTogget ? require('@/assets/ksh_xz.png') : require('@/assets/ksh.png')"
                    class="rop_item_img" />
            </div>
            <!-- 实际定位 -->
            <div class="rop_item_div" id="dw_btn" v-on:click="startLoction">
                <img :src="dwGnTogget ? require('@/assets/gps_xz.png') : require('@/assets/gps.png')"
                    class="rop_item_img" />
            </div>
        </div>

        <!-- 图层管理面板 -->
        <div class="mb_layer_mgr" id="mb_layer_mgr" :hidden="!tcMbTogget">
            <div class="mb_title_div" id="ly_close_btn" v-on:click="closeLy">
                <img src="../assets/close.png" class="mb_title_img" />
            </div>
            <div class="zdmbtm">
                <el-collapse v-model="activeNames" @change="handleChange">
                    <el-collapse-item title="遥感影像" name="1">
                        <el-row justify="start" :gutter="20" class="row_fcc">
                            <el-col :span="8" v-for="(item, index) in layerDatas.ygyx" :key="index">
                                <div class="dt_item" :class="item.isChoice ? 'checkfont' : 'checkfont_no'"
                                    @click="clickTcItem(0, index)">
                                    <img src="../assets/pic_2023.png" class="dt_item_img"
                                        :class="item.isChoice ? 'checktc' : 'checktc_no'" />
                                    <div>{{ item.name }}</div>
                                </div>
                            </el-col>
                        </el-row>
                    </el-collapse-item>
                    <el-collapse-item title="调查范围界" name="2">
                        <el-row justify="start" :gutter="20" class="row_fcc">
                            <el-col :span="8" v-for="(item, index) in layerDatas.dcfwj" :key="index">
                                <div class="dt_item" :class="item.isChoice ? 'checkfont' : 'checkfont_no'"
                                    @click="clickTcItem(1, index)">
                                    <img src="../assets/pic_fw.png" class="dt_item_img"
                                        :class="item.isChoice ? 'checktc' : 'checktc_no'" />
                                    <div>{{ item.name }}</div>
                                </div>
                            </el-col>
                        </el-row>
                    </el-collapse-item>
                    <el-collapse-item title="林地小班" name="3">
                        <el-row justify="start" :gutter="20" class="row_fcc">
                            <el-col :span="8" v-for="(item, index) in layerDatas.ldxb" :key="index">
                                <div class="dt_item" :class="item.isChoice ? 'checkfont' : 'checkfont_no'"
                                    @click="clickTcItem(2, index)">
                                    <img src="../assets/pic_xb.png" class="dt_item_img"
                                        :class="item.isChoice ? 'checktc' : 'checktc_no'" />
                                    <div>{{ item.name }}</div>
                                </div>
                            </el-col>
                        </el-row>
                    </el-collapse-item>
                    <el-collapse-item title="天地图" name="4">
                        <el-row justify="start" :gutter="20" class="row_fcc">
                            <el-col :span="8">
                                <div class="dt_item checkfont" @click="clickTcItem(-1, index)">
                                    <img src="../assets/pic_tdt.png" class="dt_item_img checktc" />
                                    <div>天地图影像</div>
                                </div>
                            </el-col>
                            <el-col :span="8">
                                <div class="dt_item checkfont" @click="clickTcItem(-1, index)">
                                    <img src="../assets/pic_td.png" class="dt_item_img checktc" />
                                    <div>天地图标注</div>
                                </div>
                            </el-col>
                        </el-row>
                    </el-collapse-item>
                </el-collapse>
            </div>
        </div>
	<!-- i键弹窗 -->
        <div style="text-align: left;">
            <el-dialog title="属性信息" :visible.sync="sxVisible" width="80%" min-height="90vh">
                <!-- <p>图层:1715918085241077760</p> -->
                <p><label>经度:</label>{{ geomCoor[0] }}</p>
                <p><label>纬度:</label>{{ geomCoor[1] }}</p>
                <!-- <p  :key="item.pk_uid">
                    {{ item }}
                </p> -->
                <div v-if="dcshuju == undefined || dcshuju.length == 0">
                    <p> 当前位置没有小班数据 </p>
                </div>
                <div v-else>
                    <div v-for="obj in dcshuju">
                        <p v-for="(value, key) in obj" :key="key" v-if="key != 'geom'">
                            {{ key }} : {{ value }}
                        </p>
                        <p style="width:100%;height: 1px;color: #ddd;"></p>
                    </div>
                </div>

            </el-dialog>
        </div>


    </div>
</template>

<script>
import "ol/ol.css";
import { Map, View, Feature } from "ol";
import TileLayer from "ol/layer/Tile";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import XYZ from "ol/source/XYZ";
import { Point } from "ol/geom";
import { Style, Icon } from "ol/style";
import { transform, fromLonLat } from "ol/proj";
import { OverviewMap, ScaleLine, defaults } from "ol/control"

export default {
    data() {
        return {
            //影像服务 token
            appToken: "填写影像服务token",
            //图层面板开关
            tcMbTogget: false,
            //属性功能开关
            sxGnTogget: false,
            //定位功能开关
            dwGnTogget: false,
            //统计功能开关
            tjGnTogget: false,

            //属性弹窗展示
            sxVisible: false,

            //图层面板类型展开记录
            activeNames: ['1', '2', '3', '4'],
            //全局地图对象
            rtsMapObj: null,
            //定位点对象
            positionNav: null,
            //当前位置经纬度
            geomCoor: [],//当前位置经纬度
            //默认mark
            defaultMark: require('@/assets/defaultIcon.png'),
            //定位mark
            positionImg: require('@/assets/position.png'),
            //定位方向
            rotate: {},

            //图层管理
            layerDatas: {
                ygyx: [],
                dcfwj: [],
                ldxb: []
            },

            dcshuju: [],


        }
    },
    components: {
    },
    /**
     * 钩子函数
     */
    mounted() {
        //初始化服务id
        this.initLayersData();
        //初始化地图
        this.initMap();
        //注册Android交互回调
        window.operationAndroidKshBord = this.operationAndroidKshBord
    },
    methods: {

        /**
         * 初始化可加载地图 (这块数据初始化可以弄成在线接口返回,后端不配合)
         */
        initLayersData() {
            let that = this;
            //添加遥感影像
            that.layerDatas.ygyx.push(
                {
                    name: "2023年影像",
                    mapId: "",
                    dataId: -1,
                    isChoice: true,
                }
            )
            that.layerDatas.ygyx.push(
                {
                    name: "2022年影像",
                    mapId: "",
                    dataId: -1,
                    isChoice: false,
                }
            )
            
            //添加调查范围界
            that.layerDatas.dcfwj.push(
                {
                    name: "三区范围",
                    mapId: "",
                    dataId: "",
                    isChoice: false,
                }
            )
            //林地小班
            that.layerDatas.ldxb.push(
                {
                    name: "林地小班2020",
                    mapId: "",
                    dataId: "",
                    isChoice: false,
                }
            )
           
        },

        /**
         * 通过数据id生成栅格图层
         * @param {*} mapId 
         */
        initLayersInfoByData(mapId) {
            let that = this;
            return new TileLayer({
                source: new XYZ({
                    crossOrigin: "anonymous",
                    projection: "EPSG:4326",
                    // tileGrid: tileGrid,
                    tileUrlFunction(tileCoord) {
                        var z = tileCoord[0];
                        var x = tileCoord[1];
                        var y = tileCoord[2];
                        let offsetZ = z
                        return 拼接的影像瓦片地址;
                    },
                    wrapX: true,
                })
            })
        },

        /**
         * 点击图层管理切换按钮
         * @param {*} typeNum 
         * @param {*} contentIndex 
         */
        clickTcItem(typeNum, contentIndex) {
            if (typeNum == -1) {
                this.$message({
                    message: '当前类型底图不允许关闭',
                    type: 'warning'
                });
                return;
            } else {
                if (typeNum == 0) {
                    this.layerDatas.ygyx.forEach(element => {
                        element.isChoice = false;
                    });
                    this.layerDatas.ygyx[contentIndex].isChoice = true
                } else if (typeNum == 1) {
                    if (!this.layerDatas.dcfwj[contentIndex].isChoice) {
                        this.layerDatas.dcfwj.forEach(element => {
                            element.isChoice = false;
                        });
                    }
                    this.layerDatas.dcfwj[contentIndex].isChoice = !this.layerDatas.dcfwj[contentIndex].isChoice
                } else if (typeNum == 2) {
                    if (!this.layerDatas.ldxb[contentIndex].isChoice) {
                        this.layerDatas.ldxb.forEach(element => {
                            element.isChoice = false;
                        });
                    }
                    this.layerDatas.ldxb[contentIndex].isChoice = !this.layerDatas.ldxb[contentIndex].isChoice
                }
                //重置地图

                this.resetZsMap()
            }
        },

        /**
         * 操作切换图层
         * return 所有加载的图层
         */
        optionLayer() {
            let tileArr = [];
            this.layerDatas.ygyx.forEach(element => {
                if (element.isChoice) {
                    //生成TileLayer
                    let item = this.initLayersInfoByData(element.mapId)
                    tileArr.push(item)
                }
            });
            //添加标注
            tileArr.push(this.initLayersInfoByData("1715918445162692608"))
            this.layerDatas.dcfwj.forEach(element => {
                if (element.isChoice) {
                    //生成TileLayer
                    let item = this.initLayersInfoByData(element.mapId)
                    tileArr.push(item)
                }
            });
            this.layerDatas.ldxb.forEach(element => {
                if (element.isChoice) {
                    //生成TileLayer
                    let item = this.initLayersInfoByData(element.mapId)
                    tileArr.push(item)
                }
            });
            return tileArr
        },

        /**
         * 获取天地图底图和标注
         */
        getBaseTdMap() {

            let tdArr = []
            //天地图底图
            var tiandiLayer = new TileLayer({
                source: new XYZ({
                    url: 'https://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=2b5ee7d7bc5d7816935c790d7d112a51',
                    //url: 'https://tiles1.geovisearth.com/base/v1/img/{z}/{x}/{y}?token=3d2f2191d56246452b6a2635ecf2d6f584d76f9ffa738c7bf7a2e85b7e354229&tmsIds=w',
                }),
                isGroup: true,
                name: '天地图路网'
            });
            //天地图标注
            var tiandiLayerBz = new TileLayer({
                source: new XYZ({
                    url: 'https://t0.tianditu.gov.cn/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=2b5ee7d7bc5d7816935c790d7d112a51'
                }),
                isGroup: true,
                name: '天地图文字标注',
            });
            tdArr.push(tiandiLayer)
            tdArr.push(tiandiLayerBz)
            return tdArr;
        },

        /**
         * 初始化地图
         */
        initMap() {
            let that = this;
            //初始中西点坐标,最大最小缩放等级设置
            const options = {
                center: [108.956220, 34.979541],
                zoom: 6,
                minZoom: 0,
                maxZoom: 18
            }

            //初始化地图
            let layersBase = this.getBaseTdMap();    //天地图底图
            let layersExts = [];     //扩展图层
            layersExts = this.optionLayer()
            this.rtsMapObj = new Map({
                // controls: ol.control.defaults({
                //     attribution: false
                // }).extend([]),
                target: 'rtsmap',
                layers: [...layersBase, ...layersExts],
                view: new View({
                    center: fromLonLat(options.center),
                    zoom: options.zoom,
                    minZoom: options.minZoom,
                    maxZoom: options.maxZoom
                }),
                controls: [new ScaleLine({ units: "metric" })]
            });
        },

        /**
         * 切换图层后重新加载地图
         */
        resetZsMap() {
            let allLay = this.rtsMapObj.getLayerGroup().getLayers().getArray();
            for (let index = allLay.length - 1; index >= 0; index--) {
                this.rtsMapObj.removeLayer(allLay[index])
            }
            //添加天地圖底圖
            this.getBaseTdMap().forEach(element => {
                this.rtsMapObj.addLayer(element)
            });
            //添加打開圖層
            this.optionLayer().forEach(element => {
                this.rtsMapObj.addLayer(element)
            });
            //关闭面板
            this.closeLy()
        },

        /**
         * 关闭图层面板
         */
        closeLy() {
            this.tcMbTogget = false;
        },

        /**
         * 打开图层面板
         */
        openLy() {
            this.tcMbTogget = true;
        },

        /**
         * 定位到当前位置
         */
        startLoction() {
            this.dwGnTogget = !this.dwGnTogget
            if (this.dwGnTogget) {
                this.positionNav = this.createLayer(this.rtsMapObj, "position");
                window.addEventListener("deviceorientation", this.orientationHandler, false);
            } else {
                //去除监听,清理定位图标
                window.removeEventListener("deviceorientation", this.orientationHandler, false);
                this.clearDwMark()
            }
        },

        /**
         * 定位事件监听
         * @param {*} event 
         */
        orientationHandler(event) {
            // console.dir(event)
            this.rotate = event.alpha;
            if (window.navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(this.dwSuccCall, this.dwFailCall, {
                    enableHighAccuracy: true,
                    timeout: 1000,
                    maximumAge: 0,
                    provider: "system",
                    coordsType: "wgs84",
                    geocode: true
                })
            }

        },

        /**
         * 定位成功回调
         * @param {*} position 
         */
        dwSuccCall(position) {
            // 这个网页获取到的坐标
            var latitude = position.coords.latitude;
            var longitude = position.coords.longitude;
            // 这个公司位置的坐标,测试使用
            var Currentposition = transform([longitude, latitude], "EPSG:4326", "EPSG:3857");
            this.positionNav.getSource().clear();
            this.addPointToMap(Currentposition, { rotation: this.rotate }, this.positionNav)
            this.rtsMapObj.getView().setCenter(Currentposition);
        },

        /**
         * 定位失败回调
         * @param {*} error 
         */
        dwFailCall(error) {
            this.positionNav.getSource().clear();
            this.addPointToMap(center, { rotation: this.rotate }, this.positionNav)
            map.getView().setCenter(center);
            // var text;
            switch (error.code) {
                case error.PERMISSION_DENIED:
                    text = "用户拒绝对获取地理位置的请求。";
                    break;
                case error.POSITION_UNAVAILABLE:
                    text = "位置信息是不可用的。";
                    break;
                case error.TIMEOUT:
                    text = "请求用户地理位置超时。";
                    break;
                case error.UNKNOWN_ERROR:
                    text = "未知错误。";
                    break;
            }
        },

        /**
         * 给地图上添加Mark
         * @param {*} lngLat 
         * @param {*} optionsPar 
         * @param {*} layer 
         */
        addPointToMap(lngLat, optionsPar, layer) {
            const options = optionsPar || {};
            const name = options.name || '标注点';
            const newFeature = new Feature({
                geometry: new Point(lngLat), // 几何信息
                name,
            });
            newFeature.attr = options.attr;
            options.src = this.positionImg;
            newFeature.setStyle(this.createIconStyle(options)); // 设置要素样式
            layer.getSource().addFeature(newFeature)
        },

        /**
         * 清除定位图标
         */
        clearDwMark() {
            this.positionNav.getSource().clear();
        },

        /**
         * 创建一个图层
         * @param {*} layerName 
         */
        createLayer(map, layerName) {
            if (map) {
                const vectorSource = new VectorSource({
                    features: [],
                    name: layerName,
                });

                const layer = new VectorLayer({
                    source: vectorSource,
                });
                layer.name = layerName;
                map.addLayer(layer);
                return layer;
            } else {
            }
        },

        /**
         * 创建Mark样式
         * @param {} optionsPar 
         */
        createIconStyle(optionsPar) {
            const options = optionsPar || {};
            const src = options.src || this.defaultMark;
            const rotation = options.rotation * Math.PI / 180.0 || 0;
            const anchorLeft = optionsPar.anchorLeft || 0.5;
            const anchorTop = optionsPar.anchorTop || 0.5;
            const scale = optionsPar.scale || 0.6;
            return new Style({
                image: new Icon({
                    anchor: [anchorLeft, anchorTop], // 锚点
                    anchorOrigin: 'bottom-right', // 锚点源
                    anchorXUnits: 'fraction', // 锚点X值单位
                    anchorYUnits: 'pixels', // 锚点Y值单位
                    offsetOrigin: 'top-right', // 偏移原点
                    opacity: 0.75,
                    src: src, // 图标的URL
                    rotation: -rotation,
                    // scale: width * 0.3 / 168.0,
                    scale: 0.5,    //图标大小
                    offset: [0, 0]
                }),
            });
        },

        /**
         * 打开属性面板
         */
        openSxLy() {
            let that = this;
            that.sxGnTogget = !that.sxGnTogget;
            if (that.sxGnTogget) {
                //地图可点
                that.rtsMapObj.on("click", (e) => {
                    const pixel = that.rtsMapObj.getEventPixel(e.originalEvent);
                    //console.dir(pixel)
                    let cor = that.rtsMapObj.getCoordinateFromPixel(pixel)
                    //console.dir(cor)
                    that.geomCoor = transform(cor, "EPSG:3857", "EPSG:4326")
                    // alert(that.geomCoor)
                    //这个坐标给后台 让他返回东西 geomCoor
                    that.getMapData();
                })
            } else {
                //地图不可点击
                that.rtsMapObj.on("click", (e) => {
                    that.sxVisible = false;
                })
            }
        },

        /**
         * 获取服务中得data数据,且展示
         */
        getMapData() {
            let that = this;
            that.dcshuju = [];
            that.geomCoor;
            let serviceArr = [];
            //获取待查询得图层
            that.layerDatas.dcfwj.forEach(element => {
                if (element.isChoice == true) {
                    serviceArr.push(element.dataId)
                }
            })
            that.layerDatas.ldxb.forEach(element => {
                if (element.isChoice == true) {
                    serviceArr.push(element.dataId)
                }
            })
            console.dir(serviceArr)
            serviceArr.forEach(element => {
                let queryParams = {
                    serviceId: element,
                    params: {
                        page: 1,
                        size: 10,
                        GEOJSON: "{ \"coordinates\": [ " + that.geomCoor[0] + ", " + that.geomCoor[1] + " ], \"type\": \"Point\" }"
                    }
                }
                let header = {
                    headers: {
                        "Content-Type": "application/json",
                        "accessToken": that.appToken
                    }
                }

                that.$axios.post("小班data数据查询地址", queryParams, header).then((res) => {
                    console.dir(res.data.data.data);
                    if (res.data.data.data && res.data.data.data.length > 0) {
                        that.dcshuju.push(res.data.data.data[0])
                    }
                    //返回一个数组
                })
            })
            //延长时间执行
            setTimeout(() => {
                that.sxVisible = true;
            }, 300)

        },

        /**
         * 统计面板打开与否
         */
        openKshLy() {
            let that = this;
            that.tjGnTogget = !that.tjGnTogget;
            //通知移动端
            that.operationAndroidKshBord()
        },

        /**
         * 图层切换面板
         * @param {*} val 
         */
        handleChange(val) {
            console.log(val);
        },

        /**
         * 操作Android端可视化面板
         */
        operationAndroidKshBord() {
            if (undefined !== window.android) {
                window.android.callAndroidFun("sendKshBord", this.tjGnTogget);
            }
        }

    },

}
</script>

<style></style>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱屋及乌#

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值