SpringBoot+Vue+Openlayers实现地图上新增和编辑坐标并保存提交
場景
若依前后端分離版手把手教你本地搭建環境并運行項目:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108465662
Vue中使用Openlayers加載Geoserver發布的ImageWMS:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/115867709
在上面搭建起來Vue+SpringBoot的前后端分離的項目的基礎上,并且加載顯示地圖之后。
要實現在地圖上顯示所有攝像頭的位置,并且可以新增時在地圖上選擇坐標,以及修改時可以在地圖上回顯坐標。
實現效果如下
新增攝像頭
修改攝像頭
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
關注公眾號
霸道的程序猿
獲取編程相關電子書、教程推送與免費下載。
實現
1、mysql設計數據庫如下
建表語句
DROP TABLE IF EXISTS `bus_surveillance_video`; CREATE TABLE `bus_surveillance_video`? (`id` int(0) NOT NULL AUTO_INCREMENT COMMENT '序號',`ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '攝像頭IP',`port` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '攝像頭端口號',`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '登錄賬號',`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '登錄密碼',`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '名稱',`area_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '區域位置',PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;2、然后使用代碼生成工具,生成相應的各層代碼。
數據庫設計主要使用area_name用來存取坐標,但是坐標是分x,y的,所以在實體類中再多加兩個屬性x和y,在新增和編輯的接口中進行
坐標的轉換。
實體類代碼:
package com.ruoyi.system.domain;import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.core.domain.BaseEntity;import java.math.BigDecimal; import java.util.List;public class BusSurveillanceVideo extends BaseEntity {private static final long serialVersionUID = 1L;/** 序號 */private Long id;/** 攝像頭IP */@Excel(name = "攝像頭IP")private String ip;/** 攝像頭端口號 */@Excel(name = "攝像頭端口號")private String port;/** 登錄賬號 */@Excel(name = "登錄賬號")private String username;/** 登錄密碼 */@Excel(name = "登錄密碼")private String password;/** 攝像頭通道 */@Excel(name = "攝像頭通道")private List channels;/** 名稱 */@Excel(name = "名稱")private String name;/** 位置x坐標 */private BigDecimal siteX;/** 位置y坐標 */private BigDecimal siteY;/** 區域名稱 */@Excel(name = "區域位置")private String areaName;public BigDecimal getSiteX() {return siteX;}public void setSiteX(BigDecimal siteX) {this.siteX = siteX;}public BigDecimal getSiteY() {return siteY;}public void setSiteY(BigDecimal siteY) {this.siteY = siteY;}public String getAreaName() {return areaName;}public void setAreaName(String areaName) {this.areaName = areaName;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void setId(Long id){this.id = id;}public Long getId(){return id;}public void setIp(String ip){this.ip = ip;}public String getIp(){return ip;}public void setPort(String port){this.port = port;}public String getPort(){return port;}public void setUsername(String username){this.username = username;}public String getUsername(){return username;}public void setPassword(String password){this.password = password;}public String getPassword(){return password;}public List getChannels() {return channels;}public void setChannels(List channels) {this.channels = channels;}@Overridepublic String toString() {return "BusSurveillanceVideo{" +"id=" + id +", ip='" + ip + '\'' +", port='" + port + '\'' +", username='" + username + '\'' +", password='" + password + '\'' +", channels=" + channels +'}';} }Mapper代碼:
package com.ruoyi.system.mapper;import com.ruoyi.system.domain.BusSurveillanceVideo;import java.util.List;public interface BusSurveillanceVideoMapper {/*** 查詢攝像頭參數** @param id 攝像頭參數ID* @return 攝像頭參數*/public BusSurveillanceVideo selectBusSurveillanceVideoById(Long id);/*** 查詢攝像頭參數列表** @param busSurveillanceVideo 攝像頭參數* @return 攝像頭參數集合*/public List<BusSurveillanceVideo> selectBusSurveillanceVideoList(BusSurveillanceVideo busSurveillanceVideo);/*** 新增攝像頭參數** @param busSurveillanceVideo 攝像頭參數* @return 結果*/public int insertBusSurveillanceVideo(BusSurveillanceVideo busSurveillanceVideo);/*** 修改攝像頭參數** @param busSurveillanceVideo 攝像頭參數* @return 結果*/public int updateBusSurveillanceVideo(BusSurveillanceVideo busSurveillanceVideo);/*** 刪除攝像頭參數** @param id 攝像頭參數ID* @return 結果*/public int deleteBusSurveillanceVideoById(Long id);/*** 批量刪除攝像頭參數** @param ids 需要刪除的數據ID* @return 結果*/public int deleteBusSurveillanceVideoByIds(Long[] ids); }mapper.xml代碼
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.system.mapper.BusSurveillanceVideoMapper"><resultMap type="BusSurveillanceVideo" id="BusSurveillanceVideoResult"><result property="id" column="id"/><result property="ip" column="ip"/><result property="port" column="port"/><result property="username" column="username"/><result property="password" column="password"/><result property="name" column="name"/><result property="areaName" column="area_name"/></resultMap><sql id="selectBusSurveillanceVideoVo">select id, ip, port, username, password, name,area_namefrom bus_surveillance_video</sql><select id="selectBusSurveillanceVideoList" parameterType="BusSurveillanceVideo"resultMap="BusSurveillanceVideoResult"><include refid="selectBusSurveillanceVideoVo"/><where><if test="ip != null and ip != ''">and ip = #{ip}</if><if test="port != null and port != ''">and port = #{port}</if><if test="username != null and username != ''">and username like concat('%', #{username}, '%')</if><if test="password != null and password != ''">and password = #{password}</if><if test="name != null and name != ''">and name = #{name}</if><if test="areaName!=null and areaName != ''">and area_name = #{areaName}</if></where></select><select id="selectBusSurveillanceVideoById" parameterType="Long" resultMap="BusSurveillanceVideoResult"><include refid="selectBusSurveillanceVideoVo"/>where id = #{id}</select><insert id="insertBusSurveillanceVideo" parameterType="BusSurveillanceVideo">insert into bus_surveillance_video<trim prefix="(" suffix=")" suffixOverrides=","><if test="id != null">id,</if><if test="ip != null">ip,</if><if test="port != null">port,</if><if test="username != null">username,</if><if test="password != null">password,</if><if test="name != null">name,</if><if test="areaName !=null ">area_name,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="id != null">#{id},</if><if test="ip != null">#{ip},</if><if test="port != null">#{port},</if><if test="username != null">#{username},</if><if test="password != null">#{password},</if><if test="name != null">#{name},</if><if test="areaName!=null">#{areaName}</if></trim></insert><update id="updateBusSurveillanceVideo" parameterType="BusSurveillanceVideo">update bus_surveillance_video<trim prefix="SET" suffixOverrides=","><if test="ip != null">ip = #{ip},</if><if test="port != null">port = #{port},</if><if test="username != null">username = #{username},</if><if test="password != null">password = #{password},</if><if test="name != null">name = #{name},</if><if test="areaName!=null">area_name =#{areaName}</if></trim>where id = #{id}</update><delete id="deleteBusSurveillanceVideoById" parameterType="Long">deletefrom bus_surveillance_videowhere id = #{id}</delete><delete id="deleteBusSurveillanceVideoByIds" parameterType="String">delete from bus_surveillance_video where id in<foreach item="id" collection="array" open="(" separator="," close=")">#{id}</foreach></delete></mapper>Service接口代碼
package com.ruoyi.system.service;import com.ruoyi.system.domain.BusSurveillanceVideo;import java.util.List;public interface IBusSurveillanceVideoService {/*** 查詢攝像頭參數** @param id 攝像頭參數ID* @return 攝像頭參數*/public BusSurveillanceVideo selectBusSurveillanceVideoById(Long id);/*** 查詢攝像頭參數列表** @param busSurveillanceVideo 攝像頭參數* @return 攝像頭參數集合*/public List<BusSurveillanceVideo> selectBusSurveillanceVideoList(BusSurveillanceVideo busSurveillanceVideo);/*** 新增攝像頭參數** @param busSurveillanceVideo 攝像頭參數* @return 結果*/public int insertBusSurveillanceVideo(BusSurveillanceVideo busSurveillanceVideo);/*** 修改攝像頭參數** @param busSurveillanceVideo 攝像頭參數* @return 結果*/public int updateBusSurveillanceVideo(BusSurveillanceVideo busSurveillanceVideo);/*** 批量刪除攝像頭參數** @param ids 需要刪除的攝像頭參數ID* @return 結果*/public int deleteBusSurveillanceVideoByIds(Long[] ids);/*** 刪除攝像頭參數信息** @param id 攝像頭參數ID* @return 結果*/public int deleteBusSurveillanceVideoById(Long id); }ServiceImpl代碼
package com.ruoyi.system.service.impl;import com.ruoyi.system.domain.BusSurveillanceVideo; import com.ruoyi.system.mapper.BusSurveillanceVideoMapper; import com.ruoyi.system.service.IBusSurveillanceVideoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;import java.math.BigDecimal; import java.util.ArrayList; import java.util.List;@Service public class BusSurveillanceVideoServiceImpl implements IBusSurveillanceVideoService {@Autowiredprivate BusSurveillanceVideoMapper busSurveillanceVideoMapper;/*** 查詢攝像頭參數** @param id 攝像頭參數ID* @return 攝像頭參數*/@Overridepublic BusSurveillanceVideo selectBusSurveillanceVideoById(Long id) {return busSurveillanceVideoMapper.selectBusSurveillanceVideoById(id);}/*** 查詢攝像頭參數列表** @param busSurveillanceVideo 攝像頭參數* @return 攝像頭參數*/@Overridepublic List<BusSurveillanceVideo> selectBusSurveillanceVideoList(BusSurveillanceVideo busSurveillanceVideo) {List<BusSurveillanceVideo> busSurveillanceVideos = busSurveillanceVideoMapper.selectBusSurveillanceVideoList(busSurveillanceVideo);busSurveillanceVideos.forEach(videos -> {videos.setChannels(new ArrayList());if (videos.getAreaName() != null) {String[] point = videos.getAreaName().substring(1, videos.getAreaName().length() - 1).split(",");if (!point[0].equals("null") && !point[1].equals("null")) {videos.setSiteX(new BigDecimal(point[0]));videos.setSiteY(new BigDecimal(point[1]));}}});return busSurveillanceVideos;}/*** 新增攝像頭參數** @param busSurveillanceVideo 攝像頭參數* @return 結果*/@Overridepublic int insertBusSurveillanceVideo(BusSurveillanceVideo busSurveillanceVideo) {String area = "[" + busSurveillanceVideo.getSiteX() + "," + busSurveillanceVideo.getSiteY() + "]";busSurveillanceVideo.setAreaName(area);return busSurveillanceVideoMapper.insertBusSurveillanceVideo(busSurveillanceVideo);}/*** 修改攝像頭參數** @param busSurveillanceVideo 攝像頭參數* @return 結果*/@Overridepublic int updateBusSurveillanceVideo(BusSurveillanceVideo busSurveillanceVideo) {String area = "[" + busSurveillanceVideo.getSiteX() + "," + busSurveillanceVideo.getSiteY() + "]";busSurveillanceVideo.setAreaName(area);return busSurveillanceVideoMapper.updateBusSurveillanceVideo(busSurveillanceVideo);}/*** 批量刪除攝像頭參數** @param ids 需要刪除的攝像頭參數ID* @return 結果*/@Overridepublic int deleteBusSurveillanceVideoByIds(Long[] ids) {return busSurveillanceVideoMapper.deleteBusSurveillanceVideoByIds(ids);}/*** 刪除攝像頭參數信息** @param id 攝像頭參數ID* @return 結果*/@Overridepublic int deleteBusSurveillanceVideoById(Long id) {return busSurveillanceVideoMapper.deleteBusSurveillanceVideoById(id);} }注意在這層實現的坐標x和坐標y的拆分顯示給前端以及組合存儲更新到數據庫。
Controller層代碼
package com.ruoyi.web.controller.system;import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.system.domain.BusSurveillanceVideo; import com.ruoyi.system.service.IBusSurveillanceVideoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*;import java.util.List;@RestController @RequestMapping("/surveillanceVideo") public class BusSurveillanceVideoController extends BaseController {@Autowiredprivate IBusSurveillanceVideoService busSurveillanceVideoService;/*** 查詢攝像頭參數列表*/@GetMapping("/getVideoInfo")public TableDataInfo list(BusSurveillanceVideo busSurveillanceVideo){startPage();List<BusSurveillanceVideo> list = busSurveillanceVideoService.selectBusSurveillanceVideoList(busSurveillanceVideo);return getDataTable(list);}/*** 獲取攝像頭參數詳細信息*/@GetMapping(value = "/{id}")public AjaxResult getInfo(@PathVariable("id") Long id){return AjaxResult.success(busSurveillanceVideoService.selectBusSurveillanceVideoById(id));}/*** 新增攝像頭參數*/@Log(title = "攝像頭參數", businessType = BusinessType.INSERT)@PostMappingpublic AjaxResult add(BusSurveillanceVideo busSurveillanceVideo){return toAjax(busSurveillanceVideoService.insertBusSurveillanceVideo(busSurveillanceVideo));}/*** 修改攝像頭參數*/@Log(title = "攝像頭參數", businessType = BusinessType.UPDATE)@PutMappingpublic AjaxResult edit(@RequestBody BusSurveillanceVideo busSurveillanceVideo){return toAjax(busSurveillanceVideoService.updateBusSurveillanceVideo(busSurveillanceVideo));}/*** 刪除攝像頭參數*/@Log(title = "攝像頭參數", businessType = BusinessType.DELETE)@DeleteMapping("/{ids}")public AjaxResult remove(@PathVariable Long[] ids){return toAjax(busSurveillanceVideoService.deleteBusSurveillanceVideoByIds(ids));} }3、前端代碼結構
前端代碼實現結構
其中Index.vue是主頁面,實現如下顯示所有攝像頭數據。
lampMap.vue是地圖顯示攝像頭頁面實現如下效果
videoMap.vue是點擊新增或者編輯時點擊選擇攝像頭時的彈窗
4、index.vue代碼
<template><div class="app-container"><el-form:model="queryParams"ref="queryForm":inline="true"v-show="showSearch"label-width="68px"><el-form-item label="名稱" prop="name"><el-inputv-model="queryParams.name"placeholder="請輸入名稱"clearablesize="small"@keyup.enter.native="handleQuery"/></el-form-item><el-form-item label="攝像頭ip" prop="ip"><el-inputv-model="queryParams.ip"placeholder="請輸入攝像頭ip"clearablesize="small"@keyup.enter.native="handleQuery"/></el-form-item><el-form-item><el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button><el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button></el-form-item></el-form><el-row :gutter="10" class="mb8"><el-col :span="1.5"><el-buttontype="primary"plainicon="el-icon-plus"size="mini"@click="handleAdd"v-hasPermi="['runcontrolmange:surveillanceVideo:add']">新增</el-button></el-col><el-col :span="1.5"><el-buttontype="success"plainicon="el-icon-edit"size="mini":disabled="single"@click="handleUpdate"v-hasPermi="['runcontrolmange:surveillanceVideo:edit']">修改</el-button></el-col><el-col :span="1.5"><el-buttontype="danger"plainicon="el-icon-delete"size="mini":disabled="multiple"@click="handleDelete"v-hasPermi="['runcontrolmange:surveillanceVideo:remove']">刪除</el-button></el-col><el-col :span="1.5"><el-buttontype="primary"icon="el-icon-map-location"size="mini"@click="showLampPointData">地圖</el-button></el-col></el-row><el-tablev-loading="loading":data="videoList"@selection-change="handleSelectionChange"><el-table-column type="selection" width="55" align="center" /><el-table-column show-overflow-tooltip label="名稱" align="center" prop="name" /><el-table-column show-overflow-tooltip label="攝像頭ip" align="center" prop="ip" /><el-table-columnshow-overflow-tooltiplabel="賬號"align="center"prop="username"/><el-table-columnshow-overflow-tooltiplabel="密碼"align="center"prop="password"/><el-table-column show-overflow-tooltip label="端口" align="center" prop="port" /><el-table-columnshow-overflow-tooltiplabel="攝像頭坐標"align="center"prop="areaName"/><el-table-column label="操作" align="center" class-name="small-padding fixed-width"><template slot-scope="scope"><el-buttonsize="mini"type="text"icon="el-icon-edit"@click="handleUpdate(scope.row)"v-hasPermi="['runcontrolmange:surveillanceVideo:edit']">修改</el-button><el-buttonsize="mini"type="text"icon="el-icon-delete"@click="handleDelete(scope.row)"v-hasPermi="['runcontrolmange:surveillanceVideo:remove']">刪除</el-button></template></el-table-column></el-table><paginationv-show="total > 0":total="total":page.sync="queryParams.pageNum":limit.sync="queryParams.pageSize"@pagination="getList"/><!-- 添加或修改識別用戶對話框 --><el-dialog :title="title" :visible.sync="open" width="500px" append-to-body><el-form ref="form" :model="form" :rules="rules" label-width="120px"><el-form-item label="名稱" prop="name"><el-input v-model="form.name" placeholder="請輸入名稱" /></el-form-item><el-form-item label="攝像頭ip" prop="ip"><el-input v-model="form.ip" placeholder="請輸入攝像頭ip" /></el-form-item><el-form-item label="賬號" prop="username"><el-input v-model="form.username" placeholder="請輸入賬號" /></el-form-item><el-form-item label="密碼" prop="password"><el-input v-model="form.password" placeholder="請輸入密碼" /></el-form-item><el-form-item label="端口" prop="port"><el-input v-model="form.port" placeholder="請輸入端口" /></el-form-item><el-form-item label="攝像頭位置" prop="coordinate"><el-input v-model="lightPoint" placeholder="點擊新增/更改攝像頭坐標" @focus="onMap" /></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button type="primary" @click="submitForm">確 定</el-button><el-button @click="cancel">取 消</el-button></div></el-dialog><!-- 地圖 --><videoMap ref="videoMap" @childEvent="parentEvent"></videoMap><lampMap ref="lampMap"></lampMap></div> </template><script> import {VideoInfoList,addVideo,updateVideo,delVideo, } from "@/api/system/carVideo"; import videoMap from "./component/videoMap"; import lampMap from "./component/lampMap";export default {name: "OpUser",components: {videoMap,lampMap,},data() {return {// 遮罩層loading: false,// 選中數組ids: [],// 非單個禁用single: true,// 非多個禁用multiple: true,// 顯示搜索條件showSearch: true,// 總條數total: 0,// 識別用戶表格數據videoList: [],// 彈出層標題title: "",// 是否顯示彈出層open: false,// 查詢參數queryParams: {pageNum: 1,pageSize: 10,},// 表單參數form: {coordinate: "",},// 表單校驗rules: {},dialogVisible: false,// 攝像頭的參數lightPoint: [],};},created() {this.getList();},mounted() {},destroyed() {},methods: {parentEvent(data) {this.form.siteX = data[0];this.form.siteY = data[1];this.lightPoint = `${this.form.siteX},${this.form.siteY}`;this.form.coordinate = this.lightPoint;},onMap() {this.$refs.videoMap.dialogVisible = true;this.$refs.videoMap.init();this.$refs.videoMap.coordinate = this.form.coordinate;this.$refs.videoMap.drawPoint([this.form.siteX, this.form.siteY]);},// 所有攝像頭地圖showLampPointData(data) {this.$refs.lampMap.dialogVisible = true;this.$refs.lampMap.init();this.$refs.lampMap.drawPoint(this.videoList);},getList() {VideoInfoList(this.queryParams).then((res) => {this.videoList = res.rows;this.total = res.total;this.loading = false;});},handleQuery() {this.queryParams.pageNum = 1;this.getList();},resetQuery() {this.resetForm("queryForm");this.handleQuery();},handleAdd() {this.reset();this.open = true;this.lightPoint = "";this.title = "新增攝像頭";},handleUpdate(row) {this.reset();this.title = "修改";this.open = true;let id;if(row.id){id = row.idthis.videoList.forEach((item) => {if (item.id == id) {this.form = JSON.parse(JSON.stringify(item));this.lightPoint = item.areaName;}});}else{id = this.ids;this.videoList.forEach((item) => {if (item.id == id[0]) {this.form = JSON.parse(JSON.stringify(item));this.lightPoint = item.areaName;}});}},/** 提交按鈕 */submitForm() {this.$refs["form"].validate((valid) => {if (valid) {if (this.form.id != null) {updateVideo(this.form).then((response) => {this.msgSuccess("修改成功");this.open = false;this.getList();});} else {addVideo(this.form).then((response) => {this.msgSuccess("新增成功");this.open = false;this.getList();});}}});},handleDelete(row) {const ids = row.id || this.ids;this.$confirm("是否確認刪除該條數據項?", "警告", {confirmButtonText: "確定",cancelButtonText: "取消",type: "warning",}).then(function () {return delVideo(ids);}).then(() => {this.getList();this.msgSuccess("刪除成功");});},cancel() {this.open = false;this.reset();},// 多選框選中數據handleSelectionChange(selection) {this.openVideoData = [];this.openVideoData = selection;this.ids = selection.map((item) => item.id);this.single = selection.length !== 1;this.multiple = !selection.length;},reset() {this.form = {ip: null,name: null,username: null,password: null,port: null,coordinate:''};this.resetForm("form");},}, }; </script> <style scoped></style>其中調用增刪改查后臺接口的代碼
? import request from '@/utils/request'export function VideoInfoList(query) {return request({url: '/surveillanceVideo/getVideoInfo',method: 'get',params: query}) } // 新增export function addVideo(query) {return request({url: '/surveillanceVideo',method: 'post',params: query}) }// 修改 export function updateVideo(query) {return request({url: '/surveillanceVideo',method: 'put',data: query}) }// 刪除 export function delVideo(id) {return request({url: '/surveillanceVideo/' + id,method: 'delete'}) }?5、index.vue關鍵代碼
點擊地圖按鈕
??????? <el-buttontype="primary"icon="el-icon-map-location"size="mini"@click="showLampPointData">地圖</el-button>顯示所有攝像頭地圖
??? // 所有攝像頭地圖showLampPointData(data) {this.$refs.lampMap.dialogVisible = true;this.$refs.lampMap.init();this.$refs.lampMap.drawPoint(this.videoList);},首先顯示lampMap組件的彈窗,其次初始化地圖,然后調用地圖畫點的方法,并傳遞所有攝像頭的坐標的list。
其中所有攝像頭坐標的list是頁面初始化請求接口獲取的。
? created() {this.getList();},然后是新增和編輯頁面點擊攝像頭位置時
??????? <el-form-item label="攝像頭位置" prop="coordinate"><el-input v-model="lightPoint" placeholder="點擊新增/更改攝像頭坐標" @focus="onMap" /></el-form-item>注意這里的onMap方法
??? onMap() {this.$refs.videoMap.dialogVisible = true;this.$refs.videoMap.init();this.$refs.videoMap.coordinate = this.form.coordinate;this.$refs.videoMap.drawPoint([this.form.siteX, this.form.siteY]);},首先是顯示頁面,其次是地圖初始化,然后是獲取form對象的coordinate屬性并傳遞給videoMap子組件的coordinate屬性
用來在地圖上進行回顯攝像頭位置。最后執行畫點的方法,參數為form表單的x坐標與y坐標。
注意這里的表單中的prop是是coordinate,但是輸入框的v-model卻是lightPoint。
這樣做才能實現彈窗之后回傳的屬性為x和y,然后表單需要提交給后臺的是拼接后的單個字符串的格式。
6.lampMap代碼
? <template><div class="cont"><el-dialogtitle="攝像頭":visible.sync="dialogVisible"width="70%":modal="false"v-loading="loading"><div id="xhdMap" v-if="dialogVisible"></div></el-dialog></div> </template><script> import Map from "ol/Map"; import View from "ol/View"; import Feature from "ol/Feature"; import { Point, LineString } from "ol/geom"; import { Image as ImageLayer, Vector as VectorLayer, Tile as TileLayer } from "ol/layer"; import { Circle, Fill, Icon, Stroke, Style, Text } from "ol/style"; import { Cluster, OSM, Vector as VectorSource, XYZ, ImageWMS, TileWMS } from "ol/source";export default {data() {return {dialogVisible: false,loading: false,layers: null,map: null,zoom: null,lightLayer: null,lightData: [],};},mounted() {},beforeDestroy() {},methods: {// 初始化地圖init() {let self = this;this.wsIsRun = true;self.$nextTick(() => {self.layers = new ImageLayer({extent: [911908.3769988124, 110617.87078181792,1596307.9757537232, 420506.5270969288],? // 邊界,source: new ImageWMS({url: "http://127.0.0.1:8000/geoserver/nyc/wms",// Layers需要指定要顯示的圖層名params: {LAYERS: "nyc:nyc_roads",exceptions: "application/vnd.ogc.se_inimage",FORMAT: "image/png",},serverType: "geoserver",}),});this.lightLayer = new VectorLayer({source: new VectorSource({ features: [] }),});// 繪制線的圖層this.map = new Map({layers: [this.layers,this.lightLayer],target: "xhdMap",view: new View({center: [987701, 213364.299370935],zoom: 12, // 放大級數maxZoom: 20,minZoom: 4,}),});});},// 畫點drawPoint(data) {let url = "";this.lightData = data;url = "/images/video.png";this.$nextTick(() => {data.forEach((item, index) => {let feature = new Feature({// geometry 幾何圖形geometry: new Point([Number(item.siteX), Number(item.siteY)]),});feature.setId(item.id);let style = new Style({image: new Icon({scale: 0.3,src: url,anchor: [0.48, 0.52],}),});feature.setStyle(style);// getSource() 獲得目前事件的事件源this.lightLayer.getSource().addFeature(feature);});});},}, }; </script> <style> #xhdMap {width: 100%;height: 80vh; } .el-dialog__header {background-color: #409eff; } .el-dialog__title, .el-dialog__close {color: #fff !important; } .el-dialog__body {padding: 5px; } </style> <style scoped> .popup {position: absolute;height: 40%;width: 30%;right: 10px;bottom: 10px;z-index: 999;color: #fff;padding: 0 15px;background: url("~@/assets/home/lamp_bg.png") no-repeat center;background-size: 100% 100%; } .msg_box {position: relative;top: calc(50% - 124px); } .msg_box div {display: flex;align-items: center;justify-content: center;margin-bottom: 4px; } .show_label {font-size: 16px;color: #ffffff;font-family: 時尚中黑;width: 150px; } .popup .msg_box /deep/ .el-input__inner {display: inline-block;color: #ffffff;background: url("~@/assets/home/input_bg.png") no-repeat;border: none;background-size: 100% 100%;width: calc(100% - 5px); } .popup .el-select {width: calc(100% - 10px); } .ol-popup-closer {text-decoration: none;position: absolute;top: -13px;right: 9px;z-index: 2001; }.ol-popup-closer:after {content: "?";font-size: 20px; } .xhd .title {line-height: 40px !important;text-indent: 0.6rem !important; } .online_state {display: inline-block;width: 10px;height: 10px;margin-right: 6px;border-radius: 50%; } .online_state_red {background: red; } .online_state_green {background: green; } </style>?7、lampMap關鍵代碼
這里繪制map時分兩個圖層,一個是顯示地圖線的圖層layers,一個是顯示攝像頭的圖層lightlayers
主要是上面點擊地圖按鈕時將所有的攝像頭的坐標數據傳遞給畫攝像頭位置的圖層的實現
??? drawPoint(data) {let url = "";this.lightData = data;url = "/images/video.png";this.$nextTick(() => {data.forEach((item, index) => {let feature = new Feature({// geometry 幾何圖形geometry: new Point([Number(item.siteX), Number(item.siteY)]),});feature.setId(item.id);let style = new Style({image: new Icon({scale: 0.3,src: url,anchor: [0.48, 0.52],}),});feature.setStyle(style);// getSource() 獲得目前事件的事件源this.lightLayer.getSource().addFeature(feature);});});}8、videoMap.vue代碼
? <template><div class="cont"><el-dialogtitle="選取攝像頭位置":visible.sync="dialogVisible"width="70%":modal="false"v-loading="loading":before-close="handleClose"><div id="pMap" v-if="dialogVisible"></div><p class="showPoint">經緯度:{{ coordinate }}</p><div class="dialogfooter"><el-button type="primary" size="small" @click="submitForm">確 定</el-button><el-button size="small" @click="cancel">取 消</el-button></div></el-dialog></div> </template><script> import Map from "ol/Map"; import View from "ol/View"; import Feature from "ol/Feature"; import { Point, LineString } from "ol/geom"; import { Circle, Fill, Icon, Stroke, Style, Text } from "ol/style"; import { getVectorContext } from "ol/render"; import { easeOut } from "ol/easing"; import { Image as ImageLayer, Vector as VectorLayer, Tile as TileLayer } from "ol/layer"; import { Cluster, OSM, Vector as VectorSource, XYZ, ImageWMS, TileWMS } from "ol/source";export default {data() {return {dialogVisible: false,loading: false,layers: null,map: null,zoom: null,lightLayer: null,coordinate: null,};},mounted() {if (this.coordinate) {this.drawPoint(this.coordinate);}},watch: {},methods: {// 初始化地圖init() {let self = this;self.$nextTick(() => {self.layers = new ImageLayer({extent: [911908.3769988124, 110617.87078181792,1596307.9757537232, 420506.5270969288], // 邊界,source: new ImageWMS({url: "http://127.0.0.1:8000/geoserver/nyc/wms",// Layers需要指定要顯示的圖層名params: {LAYERS: "nyc:nyc_roads",exceptions: "application/vnd.ogc.se_inimage",FORMAT: "image/png",},serverType: "geoserver",}),});// 攝像頭位置所放的圖層this.lightLayer = new VectorLayer({source: new VectorSource({ features: [] }),});// 繪制地圖線的圖層this.map = new Map({layers: [this.layers,this.lightLayer],target: "pMap",view: new View({//地圖中心點center: [987777.93778, 213834.81024],zoom: 12,maxZoom: 20,minZoom: 4,}),});this.onPoint();});},drawPoint(data, isTrue) {let url = "";url = "/images/video.png";this.$nextTick(() => {if (isTrue) {this.removePoint();}let feature = new Feature({// geometry 幾何圖形geometry: new Point([Number(data[0]), Number(data[1])]),});let style = new Style({image: new Icon({scale: 0.3,src: url,anchor: [0.48, 0.52],}),});feature.setStyle(style);this.lightLayer.getSource().addFeature(feature);});},removePoint() {let self = this;let allPointFeatures = self.lightLayer.getSource().getFeatures();allPointFeatures.forEach((item) => {self.lightLayer.getSource().removeFeature(item);});},onPoint() {// 監聽singleclick事件let _this = this;this.map.on("singleclick", function (e) {_this.coordinate = e.coordinate;debuggerif (_this.coordinate) {_this.drawPoint(_this.coordinate, true);}});},handleClose() {this.dialogVisible = false;},submitForm() {this.$emit("childEvent", this.coordinate);this.dialogVisible = false;},cancel() {this.dialogVisible = false;},}, }; </script> <style> #pMap {width: 100%;height: 80vh; } .el-dialog__header {background-color: #409eff; } .el-dialog__title, .el-dialog__close {color: #fff !important; } .el-dialog__body {padding: 5px; }.showPoint {position: absolute;top: 50px;color: #070707;z-index: 1;left: 50px; } .dialogfooter {position: absolute;bottom: 10px;right: 10px; } </style>?9、videoMap.vue關鍵代碼
主要是監聽地圖的單擊事件,在單擊事件中獲取坐標并賦值在左上角顯示,然后再進行繪制攝像頭圖標圖層。
??? onPoint() {// 監聽singleclick事件let _this = this;this.map.on("singleclick", function (e) {_this.coordinate = e.coordinate;debuggerif (_this.coordinate) {_this.drawPoint(_this.coordinate, true);}});},這里的繪制的方法加了一個參數,用來作為頁面上是否只留一個圖標的限制。
如果傳遞true則先清理圖層在重新繪制,保證只能有一個最新的攝像頭位置。
??????? if (isTrue) {this.removePoint();}在removePoint中遍歷所有攝像頭圖層然后刪除掉
??? removePoint() {let self = this;let allPointFeatures = self.lightLayer.getSource().getFeatures();allPointFeatures.forEach((item) => {self.lightLayer.getSource().removeFeature(item);});},最后是點擊確定時
??? submitForm() {this.$emit("childEvent", this.coordinate);this.dialogVisible = false;},將選取的坐標值傳遞給父組件。在父組件通過
??? parentEvent(data) {this.form.siteX = data[0];this.form.siteY = data[1];this.lightPoint = `${this.form.siteX},${this.form.siteY}`;this.form.coordinate = this.lightPoint;},接受傳值并分別賦值給輸入框要回顯的坐標值以及表單要提交綁定的值。
總結
以上是生活随笔為你收集整理的SpringBoot+Vue+Openlayers实现地图上新增和编辑坐标并保存提交的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 若依前后端分离/微服务版怎样构造免密链接
- 下一篇: Vue中实现页面上点击按钮下载文件(ex