场景

若依前后端分离版手把手教你本地搭建环境并运行项目:

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实现地图上新增和编辑坐标并保存提交相关推荐

  1. Vue+Openlayers实现地图上绘制线

    场景 Vue+Openlayers实现显示图片并分优先级多图层加载: Vue+Openlayers实现显示图片并分优先级多图层加载_BADAO_LIUMANG_QIZHI的博客-CSDN博客 上面是添 ...

  2. Vue+Openlayers实现地图缩放图标等比例缩放

    场景 Vue+Openlayers实现显示图片并分优先级多图层加载: Vue+Openlayers实现显示图片并分优先级多图层加载_BADAO_LIUMANG_QIZHI的博客-CSDN博客 上面实现 ...

  3. 155:vue+openlayers 设置地图的反转色、复古色、灰度图、原始图

    第155个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers中设置地图的反转色.复古色.灰度,原始状态等.采用的是CSS filter的形式. 直接复制下面的 vue+ope ...

  4. vue+openlayers实现地图打点

    前言 openlayers的使用 一.使用步骤 1.引入库 代码如下(示例):npm install ol import "ol/ol.css"; //样式 import Map ...

  5. OpenLayers 在地图上画线,获取点坐标(以天地图为例)

    应用场景: 最近在开发过程中,有个需求,需要在天地图中画线,结束后获取对应的坐标集合,查阅 OpenLayers API 和网上的相关资料后得以实现,特此记录. 因为直线间的点是无数个,我们不可能去获 ...

  6. SpringBoot+Vue+ElementUI实现文件上传与文件下载

    作者: Memory(星哥) Wechat:/QQ: 574373426 整理不易,感谢支持,欢迎 收藏 转发 分享 专注IT职业教育多年,学编程找星哥 SpringBoot+Vue+ElementU ...

  7. Android 高德地图 自己位置的显示与点地图上任意一点的坐标

    一些简单的基本配置在这里就不做介绍 效果图片如下: 1. 中间的蓝点是自己的位置 2.黄色的图标是点击的位置 3.上面TextView显示的是黄色图片的坐标 下面是代码: MainActivity p ...

  8. 如何根据地图上的两个坐标点来确定方向

    在地图上有这么两个点,黄鹤楼(A点)和黄鹤楼的公园管理处(B点),怎么确定B点在A点的什么方向呢. 在地理坐标系中可以将纬度看做直角坐标系中的Y轴,正方向由南向东北:将经度看做直角坐标系中的X轴,正方 ...

  9. vue使用百度地图获取可视区域四角坐标(百度地图四角坐标,百度地图3D可视区域四角坐标)

    百度地图api只提供了左下角和右上角两个坐标,左上角坐标和右下角坐标需要自己操作获取,方法如下: 地图自带获取坐标的方法:var bounds = map.getBounds(); //获取地图可视区 ...

最新文章

  1. 重写系统自带tabbar出现的 代理错误
  2. 蓝牙驱动卸载后自动安装_最热建筑安装工程计算表格,输入后自动生成,省时方便易上手...
  3. java web js加版本号_[Java教程]js 比较版本号(一)
  4. php mysql倒计时_php 倒计时程序
  5. jquery通过ajax方法获取json数据不执行success
  6. 第13天:页面布局实例-博雅主页
  7. VR 、AR 谁让你眼前一亮
  8. SWUST OJ(953)
  9. maven helper解决依赖冲突问题
  10. 一阶系统开环传递函数表达式_带钢纠偏液压系统模糊PID 控制与仿真
  11. Spring常用注解小结
  12. 自创RTSP 服务器 用多款客户端软件测试接入可以,唯独VLC接入不了
  13. 怎么把计算机光盘盒弹出,台式电脑10怎么弹出光驱-光驱台式机机箱打开方法
  14. 上众筹,智能手环走“全民路线”破局?
  15. No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK .
  16. 第六十九章 Caché 函数大全 $WCHAR 函数
  17. jQuery遍历对象、数组、集合
  18. SNMP协议——网络管理概述
  19. Python编程:从入门到实践------第6章:字典
  20. Android BitMap图片压缩

热门文章

  1. Future和CompletableFuture的区别和对比,以及Future主要的四个缺点——不能回调会阻塞、批量任务处理彼此依赖会阻塞、不能多个任务级联执行、得不到最先完成的任务
  2. Kobolds and Catacombs 思维,模拟,前缀,后缀(沈阳)
  3. Java多线程(五):线程池应该设置多少核心线程数
  4. 使用远程工具连接提示**Host *** is not allowed to connect to this mysql server**拒绝连接错误
  5. alias cli3 配置_vue-cli3全面配置详解
  6. mysql maria引擎_MySQL体系结构和存储引擎概述
  7. java 1e6,java-GeoPoint getLatitudeE6()返回-80000000,但getLong...
  8. er图转化为关系模式题_“助你在家自学”之无机化工流程题解法
  9. 芝枝.计算机与人文科学,2014人文并计算机学院选拔赛秩序册
  10. python多线程爬虫数据顺序_多线程爬取小说时如何保证章节的顺序