Echarts -- 百度地图基础知识学习(01)
2022-11-27 本文已影响0人
coderhzc
百度地图最近实现了,百度地图的点,线 图标更换 zoom滚动 拖动 切换...
vue项目中引入百度地图
1. 在public/index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<script
type="text/javascript"
src="https://api.map.baidu.com/getscript?v=3.0&ak='需要引入百度地图申请的AK'&services=&t=20220816154130"
></script>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to
continue.</strong
>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
2. 在main.js文件中引入:
import Vue from "vue";
import App from "./App.vue";
import ElementUI from "element-ui";
import "./assets/css/common.css"
import "./assets/css/component_style.css"
import "element-ui/lib/theme-chalk/index.css";
import core from "@/global/globalComponent"
import router from "./router";
import store from "./store";
import $axios from "@assets/js/http/http";
import * as echarts from 'echarts';
import BaiduMap from 'vue-baidu-map'
import md5 from 'js-md5';
const vueApp = function () {
$axios.get("./carcruise.webConfig.json").then(res => {
Vue.prototype.BASE_URL = res.baseUrl; //读取的请求地址挂载到vue原型
Vue.prototype.$md5 = md5;
Vue.prototype.$echarts = echarts
Vue.use(BaiduMap, {
ak: '需要引入百度地图申请的AK'
})
$axios.defaults.baseURL = res.baseUrl;
Vue.use(ElementUI);
Vue.use(core);
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
});
};
vueApp();
一.登录页面的适配
1.Login.vue
<template>
<div class="login-box">
<div class="title">
<span>巡测系统</span>
</div>
<div class="content-box">
<img class="img1"
src="@/assets/img/bg-login-zindex-left.png"
alt="">
<div class="right">
<img class="img2"
src="@/assets/img/bg-login-zindex-right.png"
alt="">
<el-button @click="login"
type="primary">进入</el-button>
</div>
</div>
</div>
</template>
<script>
export default {
methods: {
async login () {
this.$router.push("/home");
this.$message({
message: '登录成功',
type: 'success'
});
}
}
}
</script>
<style lang="less" scoped>
.login-box {
background: url(../../assets/img/bg-login.png) center center no-repeat;
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
.title {
text-align: center;
padding: 35px 0;
font-family: "ZhenyanGB";
font-style: normal;
font-weight: 400;
font-size: 52px;
line-height: 53px;
letter-spacing: 0.1em;
color: #3f85fb;
user-select: none;
}
.content-box {
margin-top: 10px;
text-align: center;
.img1,
.img2 {
height: 80vh;
border-radius: 4px;
-webkit-user-drag: none;
}
.right {
position: relative;
display: inline-block;
margin-left: -10px;
text-align: center;
border-radius: 4px;
.el-button {
position: absolute;
bottom: 20%;
right: 9%;
border: none;
color: #fff;
max-width: 90vw;
min-width: 16vw;
height: 32px;
line-height: 10px;
border-radius: 20px;
}
}
}
}
</style>
实际截图
image.png二. 百度地图实现自定义marker 实现zoom滚动 地图拖动, 点击maker实现弹框弹出
2.1 father.vue
<template>
<div class="trajectory-chart-box">
<el-card class="box-card">
<template #header>
<div style="display: flex;justify-content: space-between;cursor: pointer;">
<div class="f-c f-16">
<span>实时轨迹图</span>
<el-dropdown class="m-t-10 m-l-10"
@command="selectBridgeData">
<span class="el-dropdown-link span-style">
{{ selectBridgeDataTitle }}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="0">全部</el-dropdown-item>
<el-dropdown-item :command="1">雄楚大道高架桥上车载巡测数据</el-dropdown-item>
<el-dropdown-item :command="2">雄楚大道高架桥下车载巡测数据</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button type="primary"
style="margin-left:10px;"
size="mini"
@click="InitMap">查看</el-button>
</div>
<el-dropdown class="m-t-10"
@command="handleCommand">
<span class="el-dropdown-link span-style">
{{ spanTitle }}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="1">积分场强</el-dropdown-item>
<el-dropdown-item :command="2">电场强度占标率</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<keep-alive>
<div id="allmap"
class="Map" />
</keep-alive>
<div class="shadow-box"> <img :src="typeNumber === 1? dataArea1:dataArea2"
alt=""></div>
</el-card>
<car-dialog :title="isType ==='detail'? '详情': '频谱数据'"
:isShowBtn="false"
:width="'40%'"
@handleClose="isShow=false"
@submit="isShow=false"
:destroy-on-close="true"
:visible='isShow'>
<div v-if="isType === 'detail'"
style="min-height: 35vh;">
<el-table :data="detailTableData"
style="width: 100%"
class="ones"
min-height="260"
max-height="460"
stripe
:header-cell-style="{background:'#F2F3F5'}">
<el-table-column type="index"
width="50" />
<el-table-column prop="etotal"
label="积分场强(V/m)"
show-overflow-tooltip
width="120">
</el-table-column>
<el-table-column prop="enormal"
label="电场强度占标率(%)"
show-overflow-tooltip
width="180">
<template slot-scope="scope">
<span>{{(scope.row.enormal.toFixed(2)) + "%"}}</span>
</template>
</el-table-column>
<el-table-column prop="time"
show-overflow-tooltip
label="时间"
center
width="200">
</el-table-column>
<el-table-column fixed="right"
label="详细地址"
show-overflow-tooltip
width="240"
prop="address">
</el-table-column>
<el-table-column fixed="right"
label="频谱数据"
width="80">
<template slot-scope="scope">
<el-button type="text"
size="small"
@click="handleClick(scope.row)"
v-preventReClick>查看</el-button>
</template>
</el-table-column>
</el-table>
<div style="text-align: right;"
class="m-t-10">
<el-pagination @current-change.sync="handleCurrentChange"
v-if="detailTableData.length > 0"
:current-page="tableObj.pageNumber"
:page-size.sync="tableObj.pageSize"
background
layout="total, prev, pager, next"
:total="tableObj.count">
</el-pagination>
</div>
</div>
<div v-else
style="min-height: 35vh;">
<TrajectoryChildChart :deviceguid='deviceguidObj'
@backIshow="backIshow"
:type="typeNumber" />
</div>
</car-dialog>
</div>
</template>
<script>
import { GetSimpleByZoom, GetRecordById } from "@services/Track/Track.js";
import TrajectoryChildChart from "./TrajectoryChildChart/TrajectoryChildChart.vue";
import { getDotPic } from "@/utils/getDotPic.js";
// import { styleJson } from "@/utils/mapStyle.js"
export default {
name: 'Mapbox',
components: {
TrajectoryChildChart
},
data () {
return {
selectBridgeDataTitle: "全部",
typeNumber: 1,
tableObj: {
pageIndex: 1,
pageSize: 10,
count: 0,
},
itemInfo: null,
dataArea1: require('@/assets/img/data_area1.png'),
dataArea2: require('@/assets/img/data_area2.png'),
spanTitle: "积分场强",
isType: "详情",
detailTableData: [],
isShow: false,
getSimpleByZoomData: {
minJd: "", // 最小经度
maxJd: "", // 最大经度
minWd: "",// 最小纬度
maxWd: "",// 最大纬度
zoom: 12, // 层级
Device: ""
},
markerList: [],
click_jd: "",
click_wd: "",
addreaaMsg: "",
deviceguidObj: null
}
},
mounted () {
this.InitMap();
},
watch: {
"tableObj.pageIndex": {
deep: true,
handler (newValue, oldValue) {
this.getTableDataInfo()
}
}
},
methods: {
selectBridgeData (val) {
switch (val) {
case 0:
this.selectBridgeDataTitle = "全部"
break;
case 1:
this.selectBridgeDataTitle = "雄楚大道高架桥上车载巡测数据"
break;
case 2:
this.selectBridgeDataTitle = "雄楚大道高架桥下车载巡测数据"
break;
}
},
handleCurrentChange (val) {
this.tableObj.pageIndex = val
},
async getTableDataInfo () {
console.log(this.itemInfo.id);
const res = await GetRecordById({ id: this.itemInfo.id, pageIndex: this.tableObj.pageIndex, pageSize: this.tableObj.pageSize })
this.$nextTick(() => {
this.tableObj.count = res.total
this.detailTableData = res?.data.map(r => {
r.address = this.addreaaMsg
return r
})
})
},
backIshow () {
this.isType = 'detail'
},
handleCommand (e) {
this.typeNumber = e
this.typeNumber === 1 ? this.spanTitle = "积分场强" : this.spanTitle = '电场强度占标率';
this.InitMap();
},
async handleClick (val) {
this.deviceguidObj = val;
this.isType = "allDetail"
},
InitMap () {
var _this = this;
var map = new BMap.Map("allmap", { enableMapClick: false, features: ['road', 'bg'] }); //初始化map, 绑定id=allmap
var top_left_control = new BMap.ScaleControl({ anchor: BMAP_ANCHOR_TOP_LEFT });// 左上角,添加比例尺
map.addControl(top_left_control);
map.enableScrollWheelZoom();// 开启滚动鼠标滑轮
// 这个是拖拽事件
map.addEventListener('moveend', async function (e) {
await _this.addEventChange(map, _this)
})
// 滚轮事件
map.addEventListener('zoomend', async function (e) {
await _this.addEventChange(map, _this)
})
var point = new BMap.Point(114.404722, 30.572849); // 初始化point, 给定一个默认x,y值
map.centerAndZoom(point, 12); // 将point点放入map中,展示在页面中心展示,10=缩放程度
// map.setMapStyle({ style: 'googlelite' });
map.setMapStyleV2({
styleId: '430895908c5d4775c3fa9499327603c7'
})
},
async addEventChange (map, _this) {
var bounds = map.getBounds(); //获取地图可视区域
var sw = bounds.getSouthWest(); //获取西南角的经纬度(左下端点)
var ne = bounds.getNorthEast();//获取东北角的经纬度(右上端点)
var zoomData = map.getZoom()
_this.getSimpleByZoomData.minJd = sw.lng || 114.42599422186427
_this.getSimpleByZoomData.maxJd = ne.lng || 30.67950267377038
_this.getSimpleByZoomData.minWd = sw.lat || 114.06149777813562
_this.getSimpleByZoomData.maxWd = ne.lat || 30.39931702412463
var zoomData = map.getZoom()
_this.getSimpleByZoomData.zoom = zoomData || 12
_this.getSimpleByZoomData.Device = this.selectBridgeDataTitle == '全部' ? '' : this.selectBridgeDataTitle == '雄楚大道高架桥上车载巡测数据' ? 'PPXC11' : 'PPXC01'
const res1 = await GetSimpleByZoom(_this.getSimpleByZoomData)
let data = res1.data
//移除之前的绘点
_this.markerList.map(v => {
if (v) {
v.remove()
}
})
_this.markerList = []
data.forEach((e) => {
// 创建point, 将x,y值传入
let pointNumber = new BMap.Point(e.jd, e.wd)
// 创建信息窗口对象
let infoWindow = new BMap.InfoWindow("", {
width: 210, // 信息窗口宽度
height: 130, // 信息窗口高度
title: `<div class='m-t-10'>
<div style='display: flex;justify-content: space-between;'>
<span class='title-address'></span>
<span class='check-detail' style='color:#419eff;cursor: pointer;'>查看详情</span>
</div>
<div>
<span>积分场强:</span>
<span>${e.etotal.toFixed(2)}</span>
</div>
<div>
<span>电场强度占标率:</span>
<span>${(e.enormal).toFixed(2) + '%'}</span>
</div>
<div>
<span>经度:</span>
<span>${e.jd}</span>
</div>
<div>
<span>纬度:</span>
<span>${e.wd}</span>
</div>
</div>`// 信息窗口标题
});
_this.markerFun(pointNumber, infoWindow, e, _this.typeNumber, map, _this)
})
},
markerFun (points, infoWindows, item, typeNumber, map, _this) {
let png = getDotPic(typeNumber, item);// 点在地图显示的标记
var myIcon = new BMap.Icon(png, new BMap.Size(18, 18), { anchor: new BMap.Size(0, 0), imageOffset: new BMap.Size(5, 5) })
let markerOptions = {
enableMassClear: false,
icon: myIcon
}
let markers = new BMap.Marker(points, markerOptions);
console.log('markers', markers.count);
map.addOverlay(markers); // 将标注添加到地图中
map.clearOverlays()
// 标注的点击事件
markers.addEventListener("click", async (e) => {
var pointMarker = new BMap.Point(item.jd, item.wd);
var myGeo = new BMap.Geocoder();
myGeo.getLocation(pointMarker, (rs) => {
var addComp = rs.addressComponents;
_this.$nextTick(() => {
_this.addreaaMsg = addComp.province + ", " + addComp.city + ", " + addComp.district;
document.querySelector(".title-address").innerHTML = addComp.district;
})
});
map.openInfoWindow(infoWindows, points);//参数:窗口、点 根据点击的点出现对应的窗口
document.querySelector(".check-detail") ? document.querySelector(".check-detail").onclick = async (e) => {
_this.isType = "detail"
_this.itemInfo = item
_this.isShow = true;// 弹框显示
await _this.getTableDataInfo()
} : ''
})
_this.markerList.push(markers)
},
}
}
</script>
<style lang="less" scoped>
.trajectory-chart-box {
position: relative;
}
.box-card {
height: 100%;
text-align: center;
.shadow-box {
width: 140px;
height: 78vh;
position: absolute;
right: 20px;
bottom: -10px;
margin-bottom: 30px;
background: linear-gradient(
270deg,
#d9d9d9 0%,
rgba(217, 217, 217, 0) 162.68%
);
opacity: 0.8;
}
img {
position: absolute;
-webkit-user-drag: none;
right: -26px;
bottom: 20px;
}
}
.Map {
height: 78vh;
width: 100%;
}
.check-detail {
color: #419eff !important;
cursor: pointer;
margin-left: 10px;
background-color: none;
}
/deep/.el-dropdown {
background: #f2f3f5;
height: 30px;
padding: 5px;
border-radius: 2px;
}
</style>
实际截图
image.png<template>
<div>
<div class="pop-box"
v-if="resStatus == 200">
<el-button size="mini"
type="primary"
@click="backGo">返回</el-button>
<el-row class="t-a-c">
<el-col :span="12">
<div>
<span>最小频率:</span>
<span class="show-style">{{ this.detailObj && this.detailObj.minFreq || "" }}</span>
<span class="f-c-0">MHz</span>
</div>
</el-col>
<el-col :span="12">
<div>
<span>最大频率:</span>
<span class="show-style">{{ this.detailObj && this.detailObj.maxFreq || "" }}</span>
<span class="f-c-0">MHz</span>
</div>
</el-col>
</el-row>
<el-row class="t-a-c m-t-10">
<el-col :span="12">
<div style="margin-left:-5px;">
<span>积分场强:</span>
<span class="show-style">{{ deviceguid.etotal || "" }}</span>
<span class="f-c-0">V/m</span>
</div>
</el-col>
<el-col :span="12">
<div style="margin-left:-60px;">
<span>电场强度占标率:</span>
<span class="show-style">{{ deviceguid.enormal || "" }}</span>
<span class="f-c-0">%</span>
</div>
</el-col>
</el-row>
<div class="echarts-box">
<span class="vm-title">V/m</span>
<div class="com-chart"
id="main"
style="max-width: 100%;min-height: 50vh;"></div>
<span class="mhz-title">MHz</span>
</div>
</div>
<div class="pop-box"
v-else>
<el-result icon="warning"
title="该位置无频谱测量数据"
subTitle="">
<template slot="extra">
<el-button size="mini"
type="primary"
@click="backGo">返回</el-button>
</template>
</el-result>
</div>
</div>
</template>
<script>
import { GetListByDeviceguid } from "@services/Track/Track.js";
import * as echarts from 'echarts';
export default {
data () {
return {
detailObj: "",
resStatus: 200
}
},
props: {
deviceguid: {
type: Object,
default () {
return {}
}
},
type: {
type: Number,
default: 1
}
},
mounted () {
this.getData();
},
methods: {
backGo () {
this.$emit("backIshow")
},
async getData () {
const res = await GetListByDeviceguid({ deviceguid: this.deviceguid.deviceguid });
this.resStatus = res.code
if (res.code === 500) {
return ""
}
this.detailObj = res.data
this.initChart(res.data.data)
},
initChart (data) {
let chartDom = document.getElementById('main');
let myChart = echarts.init(chartDom);
let option = {
tooltip: {
trigger: 'axis',
// formatter: (params) => {
// // console.log(params);
// let templete = '';
// if (params.seriesType === 'line') {
// templete = '频率: ' + params.data[0] + '<br />' + "积分场强: " + params.data[1]
// }
// return templete
// },
},
grid: {
containLabel: true,
top: '8%',
left: '3%',
right: '8%',
bottom: '5%',
show: true,
backgroundColor: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(8,20,48,0.9)"
},
{
offset: 1,
color: "rgba(8,20,48,0.9)"
}
]),
borderColor: "rgba(8,20,48)"
},
xAxis: {
// name: 'MHz',
type: 'value',
interval: 2999.95, // 步长
min: 0.1, // 起始
max: 6000, // 终止
// nameTextStyle: { // y轴name的样式调整
// color: '#000',
// fontSize: 14,
// },
splitLine: {
show: true,
lineStyle: {
type: "solid",
color: " #334984",
},
},
},
yAxis: {
// name: 'V/m',
type: 'log',
min: 0.00001,
// nameTextStyle: { // y轴name的样式调整
// color: '#000',
// fontSize: 16,
// },
max: 100,
logBase: 10,
splitLine: {
lineStyle: {
color: " #334984",
}
},
},
series: [
{
showSymbol: false,
type: 'line',
data: data
}
]
};
option && myChart.setOption(option);
window.addEventListener('resize', function () {
myChart.resize();
});
}
}
}
</script>
<style scoped lang="less">
/deep/.el-button--primary {
color: #fff;
background-color: #3f85fb;
border-color: #409eff;
}
.show-style {
display: inline-block;
width: 95px;
height: 32px;
line-height: 32px;
background: #f2f3f5;
border-radius: 2px;
margin: 0 3px;
}
.echarts-box {
position: relative;
.vm-title {
position: absolute;
font-size: 16px;
color: #000;
left: 60px;
top: 0;
}
.mhz-title {
position: absolute;
font-size: 16px;
color: #000;
bottom: 22px;
right: 5px;
}
.com-chart {
margin-top: 10px;
margin-left: 15px;
}
}
</style>
实际截图:
image.png老版截图
image.png三. 热力图的更新
<template>
<div class="trajectory-chart-box">
<el-card class="box-card">
<template #header>
<div style="display: flex;justify-content: space-between;cursor: pointer;">
<div class="f-c f-16">实时态势图</div>
<el-dropdown class="m-t-10"
@command="handleCommand">
<span class="el-dropdown-link span-style">
{{spanTitle}}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="1">积分场强</el-dropdown-item>
<el-dropdown-item :command="2">电场强度占标率</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<div id="main"
style="min-width: 95%;min-height: 82vh"></div>
<div class="shadow-box">
<img :src="level === 1? dataArea1:dataArea2"
alt="">
</div>
</el-card>
</div>
</template>
<script>
import * as echarts from 'echarts';
import 'echarts/extension/bmap/bmap';
import { GetDeviserHeatmap } from "@services/DynamicChart/DynamicChart.js";
import { styleJson } from "@/utils/mapStyle.js"
import { BmlHeatmap } from 'vue-baidu-map'//引人
export default {
components: {//注册
BmlHeatmap
},
data () {
return {
level: 1,
spanTitle: "积分场强",
dataArea1: require('@/assets/img/data_area1.png'),
dataArea2: require('@/assets/img/data_area2.png'),
myChart: null,
zoom: 12,
color: ['#73C2FB', '#1E90FF', '#2A52BE', '#90EE90', '#32CD32', '#008000', '#FFDF00', '#FFA500', '#FF4500', '#FF0000'],
mapList: []
}
},
mounted () {
this.initThermodynamicCharts()
},
watch: {
zoom (oldVal, newVal) {
if (this.zoom > 15) {
return this.zoom = 15
}
if (this.zoom < 12) {
return this.zoom = 12
}
if (oldVal !== newVal) this.initThermodynamicCharts(this.zoom)
}
},
methods: {
listenerZoom () {
var _this = this
_this.$nextTick(() => {
_this.myChart.on("bmaproam", async (params) => {
if (params.dy || params.dx) return; //如果是拖拽事件则退出
let _option = _this.myChart.getOption();
_this.zoom = _option.bmap[0].zoom; //获取当前缩放比例zoom
})
});
},
handleCommand (e) {
this.level = e
this.spanTitle = this.level === 1 ? "积分场强" : '电场强度占标率'
this.initThermodynamicCharts()
},
async initThermodynamicCharts () {
const res = await GetDeviserHeatmap({ zoom: this.zoom });
console.log(res);
let points = res?.data.map(item => {
if (this.zoom === 12) {
return [item.jd, item.wd, this.level === 1 ? (item.eTotalLevel * 0.5) : (item.eNormalLevel * 0.5)]
} else if (this.zoom === 13) {
return [item.jd, item.wd, this.level === 1 ? (item.eTotalLevel) : (item.eNormalLevel)]
} else if (this.zoom === 14) {
return [item.jd, item.wd, this.level === 1 ? (item.eTotalLevel * 1.2) : (item.eNormalLevel * 1.2)]
} else if (this.zoom === 15) {
return [item.jd, item.wd, this.level === 1 ? (item.eTotalLevel * 1.5) : (item.eNormalLevel * 1.5)]
}
})
var chartDom = document.getElementById('main');
var myChart = echarts.init(chartDom);
var option;
myChart.setOption(
(option = {
animation: false,
bmap: {
center: [114.404722, 30.572849],
zoom: this.zoom,
roam: true,
setMapStyle: {
styleJson
}
},
visualMap: {
show: false,
top: 'top',
min: 0,
max: 10,
seriesIndex: 0,
calculable: true,
inRange: {
color: ['#73C2FB', '#1E90FF', '#2A52BE', '#90EE90', '#32CD32', '#008000', '#FFDF00', '#FFA500', '#FF4500', '#FF0000']
}
},
series: [
{
type: 'heatmap',
coordinateSystem: 'bmap',
data: points,
pointSize: 5,
blurSize: 6,
}
]
})
);
// 添加百度地图插件
// var bmap = myChart.getModel().getComponent('bmap').getBMap();
// bmap.addControl(new BMap.MapTypeControl());
myChart.getModel().getComponent('bmap').getBMap();
option && myChart.setOption(option);
console.log(this.zoom,);
this.myChart = myChart;
console.log(this.myChart);
this.listenerZoom();
}
}
}
</script>
<style lang="less" scoped>
.trajectory-chart-box {
// position: relative;
.box-card {
box-sizing: border-box;
position: relative;
text-align: center;
.shadow-box {
width: 140px;
height: 87%;
position: absolute;
right: 18px;
bottom: 5px;
margin-bottom: 30px;
background: linear-gradient(
270deg,
#d9d9d9 0%,
rgba(217, 217, 217, 0) 162.68%
);
opacity: 0.8;
}
img {
-webkit-user-drag: none;
position: absolute;
right: -26px;
bottom: 20px;
}
#main {
margin-top: 10px;
}
}
}
/deep/.el-card__body {
padding: 0 !important;
}
/deep/ .ec-extension-bmap {
height: 87% !important;
width: 97.5% !important;
margin: 10px 20px !important;
}
</style>
实际截图
image.png四. 网格图
<template>
<div class="trajectory-chart-box">
<el-card class="box-card">
<template #header>
<div style="display: flex;justify-content: space-between;cursor: pointer;">
<div class="f-c f-16">实时网格图</div>
<el-dropdown class="m-t-10"
@command="handleCommand">
<span class="el-dropdown-link span-style">
{{ spanTitle }}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="1">积分场强</el-dropdown-item>
<el-dropdown-item :command="2">电场强度占标率</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<div id="main"
ref="myCharts"
style="min-width: 100%;min-height: 78vh;"></div>
<div class="shadow-box">
<span class="map-zoom">地图层级:{{ zoom }}</span>
<span class="map-zoom">网格大小</span>
<div style="padding-left: 55px">长:{{ gridsize > 1000 ? (gridsize / 1000) + ' KM': gridsize + " M" }}</div>
<div style="padding-left: 55px">宽:{{ gridsize > 1000 ? (gridsize / 1000) + ' KM': gridsize + " M" }}</div>
<img :src="level === 1? dataArea1:dataArea2"
alt="">
</div>
</el-card>
</div>
</template>
<script>
import * as echarts from 'echarts';
import 'echarts/extension/bmap/bmap';
import { GetDeviserArea } from "@services/GridChart/GridChart.js";
import { styleJson } from "@/utils/mapStyle.js"
export default {
data () {
return {
level: 1,
spanTitle: "积分场强",
myChart: null,
zoom: 13,
gridsize: 0,
dataArea1: require('@/assets/img/data_area1.png'),
dataArea2: require('@/assets/img/data_area2.png'),
}
},
async mounted () {
await this.initGridChart(12)
this.getZoom()
},
methods: {
listenerZoom () {
var _this = this
_this.$nextTick(() => {
_this.myChart.on("bmaproam", async (params) => {
if (params.dy || params.dx) return; //如果是拖拽事件则退出
let _option = _this.myChart.getOption();
let res = _option.bmap[0].center
// _this.center1[0] = res[1]
// _this.center2[0] = res[0]
_this.zoom = _option.bmap[0].zoom; //获取当前缩放比例zoom
})
});
},
handleCommand (e) {
this.level = e
this.spanTitle = this.level === 1 ? "积分场强" : '电场强度占标率'
this.initGridChart()
},
removeEcharts () {
this.myChart.remove()
},
async initGridChart () {
const res = await GetDeviserArea({ zoom: this.zoom });
let gridList = this.level === 1 ? res.data.dataETotal : res.data.dataENormal
this.gridsize = res.data.len
var chartDom = document.getElementById('main');
var myChart = echarts.init(chartDom);
let COLORS = ["rgba(255,255,255,.2)", '#73C2FB', '#1E90FF', '#2A52BE', '#90EE90', '#32CD32', '#008000', '#FFDF00', '#FFA500', '#FF4500', '#FF0000',];
var lngExtent = [30.485342, 30.789517];
var latExtent = [114.17957, 114.465906];
// var cellCount = [50,50]
var cellCount = this.zoom === 13 ? [10, 10] : this.zoom === 14 ? [20, 20] : this.zoom === 15 ? [30, 30] : this.zoom === 16 ? [40, 40] : [50, 50];
var cellSizeCoord = [
(lngExtent[1] - lngExtent[0]) / cellCount[0],
(latExtent[1] - latExtent[0]) / cellCount[1]
];
function renderItem (params, api) {
var lngIndex = api.value(0);
var latIndex = api.value(1);
var coordLeftTop = [
+(latExtent[0] + lngIndex * cellSizeCoord[0]).toFixed(6),
+(lngExtent[0] + latIndex * cellSizeCoord[1]).toFixed(6)
];
var pointLeftTop = getCoord(params, api, lngIndex, latIndex);
var pointRightBottom = getCoord(params, api, lngIndex + 1, latIndex + 1);
return {
type: 'rect',
shape: {
x: pointLeftTop[0],
y: pointLeftTop[1],
width: pointRightBottom[0] - pointLeftTop[0],
height: pointRightBottom[1] - pointLeftTop[1]
},
style: api.style({
stroke: 'rgba(0,0,0,0.1)'
}),
styleEmphasis: api.styleEmphasis()
};
}
function getCoord (params, api, lngIndex, latIndex) {
var coords = params.context.coords || (params.context.coords = []);
var key = lngIndex + '-' + latIndex;
return (
coords[key] ||
(coords[key] = api.coord([
+(latExtent[0] + lngIndex * cellSizeCoord[0]).toFixed(6),
+(lngExtent[0] + latIndex * cellSizeCoord[1]).toFixed(6)
]))
);
}
var _this = this
var option = {
tooltip: {
formatter: function (res) {
return _this.level === 1 ? "积分场强: " + res.data[3] : "电厂强度占标率: " + res.data[3]
}
},
visualMap: {
type: 'piecewise',
inverse: true,
top: 10,
left: 10,
pieces: [
{
value: 0,
color: COLORS[0]
},
{
value: 1,
color: COLORS[1]
},
{
value: 2,
color: COLORS[2]
},
{
value: 3,
color: COLORS[3]
},
{
value: 4,
color: COLORS[4]
},
{
value: 5,
color: COLORS[5]
},
{
value: 6,
color: COLORS[6]
},
{
value: 7,
color: COLORS[7]
},
{
value: 8,
color: COLORS[8]
},
{
value: 9,
color: COLORS[9]
}
],
show: false,
borderColor: '#ccc',
borderWidth: 2,
backgroundColor: '#eee',
dimension: 2,
inRange: {
color: COLORS,
opacity: 0.7
},
},
series: [
{
type: 'custom',
coordinateSystem: 'bmap',
renderItem: renderItem,
animation: false,
emphasis: {
itemStyle: {
color: '#ccc'
}
},
encode: {
tooltip: 2
},
data: gridList
}
],
bmap: {
center: [114.304722, 30.599849],
zoom: this.zoom,
roam: true,
setMapStyle: {
styleJson
}
}
};
option && myChart.setOption(option, true);
this.myChart = myChart;
this.listenerZoom();
},
getZoom () {
if (this.zoom === 13) {
this.initGridChart(13)
}
}
},
watch: {
gridsize (r, i) {
this.gridsize = parseInt(r)
},
zoom (oldVal, newVal) {
if (this.zoom > 17) {
return this.zoom = 17
}
if (this.zoom < 13) {
return this.zoom = 13
}
if (oldVal !== newVal) this.initGridChart(this.zoom)
},
}
}
</script>
<style lang="less" scoped>
.trajectory-chart-box {
position: relative;
img {
-webkit-user-drag: none;
position: absolute;
right: -20px;
bottom: 20px;
}
.box-card {
min-width: 100%;
min-height: 78vh;
overflow: scroll;
// text-align: center;
.shadow-box {
width: 140px;
height: 78vh;
position: absolute;
right: 20px;
bottom: -3px;
margin-bottom: 30px;
background: linear-gradient(
270deg,
#d9d9d9 0%,
rgba(217, 217, 217, 0) 162.68%
);
.map-zoom {
display: inline-block;
padding: 10px 10px 0 10px;
color: #000;
}
}
img {
position: absolute;
right: -26px;
bottom: 20px;
}
}
}
</style>
实际截图
image.png五. 人工平行线画格子
<template>
<div class="trajectory-chart-box">
<el-card class="box-card">
<template #header>
<div style="display: flex;justify-content: space-between;cursor: pointer;">
<div class="artificial-issuee">
<el-upload class="upload-demo"
action="https://jsonplaceholder.typicode.com/posts/"
multiple
:limit="3">
<el-button size="mini"
type="primary">导入文件</el-button>
</el-upload>
<el-button @click="changeArtificialGrid"
size="mini"
type="primary"
style="margin-left:10px;">切换人工测量</el-button>
</div>
<el-dropdown class="m-t-10"
@command="handleCommandTitle">
<span class="el-dropdown-link">
{{ spanTitle }}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="1">积分场强</el-dropdown-item>
<el-dropdown-item :command="2">电场强度占标率</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<div>
<div id="allmap"
v-if="artificObj.isShowArtificialAndDefault"
class="map-box"></div>
<baidu-map v-else
class="map-box"
:center="{lng: 114.381294, lat: 30.622897}"
:zoom="artificObj.zoom"
@click="paintPolyline"
@ready="handler"
center="武汉"
@mousemove="syncPolyline"
:scroll-wheel-zoom="true"
ak="GVelNGs7fvSLFlcssQrxVPpKSvdUHFIH"
@rightclick="newPolyline">
<bm-scale anchor="BMAP_ANCHOR_TOP_LEFT"></bm-scale>
<bm-control>
<el-button type="primary"
style="margin:15px 0 0 200px"
size="mini"
@click="toggle('polyline')">{{ polyline.editing ? '停止绘制' : '开始绘制' }}</el-button>
<el-button size="mini"
type="primary"
style="margin:20px 0 0 10px;"
@click="clearGrid"
v-preventReClick>清除覆盖物</el-button>
</bm-control>
<bm-polyline :path="path"
v-for="path of polyline.paths"></bm-polyline>
<bm-polygon v-for="path in polyline.polylinePath"
:path="path"
stroke-color="blue"
:stroke-opacity="0.5"
:stroke-weight="2"
:editing="false"></bm-polygon>
</baidu-map>
</div>
<div class="shadow-box">
<div class="scheme-box">
<div v-if="artificObj.isShowArtificialAndDefault">
<span>选择方案:</span>
<el-dropdown class="m-l-10"
style="width:116px;"
@command="handleCommand">
<span class="el-dropdown-link"
style="color:#1D2129; padding-left:8px">
<b> {{ spanRightTitle }}</b>
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="1">方案一</el-dropdown-item>
<el-dropdown-item :command="2">方案二</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<p class="m-t-10">(*方案一:500m*500m网格
方案二:1km*1km网格)
</p>
<img :src="typeNumber === 1? dataArea1:dataArea2"
alt="" />
</div>
<div v-else>
<span>起始点:</span>
<el-input v-model="artificObj.startDot"
disabled
placeholder="坐标"></el-input>
<span>结束点:</span>
<el-input v-model="artificObj.endDot"
placeholder="坐标"
disabled></el-input>
<span>选择网格大小:</span>
<el-dropdown class="m-l-10"
style="width:116px;"
@command="handleCommandMClick">
<span class="el-dropdown-link"
style="color:#1D2129; padding-left:1px;display:flex;">
<div> {{ artificObj.spanRightTitleMi }}</div>
<i class="el-icon-arrow-down m-l-10"
style="padding-top:2px;"></i>
</span>
<el-dropdown-menu slot="dropdown">
<!-- <el-dropdown-item :command="1">100*100</el-dropdown-item>
<el-dropdown-item :command="2">200*200</el-dropdown-item> -->
<el-dropdown-item :command="3">500*500</el-dropdown-item>
<el-dropdown-item :command="4">1000*1000</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button size="mini"
type="primary"
style="margin:20px 0 0 10px; width:118px;"
@click="paintGrid"
v-preventReClick>绘制网格</el-button>
</div>
</div>
</div>
</el-card>
</div>
</template>
<script>
import 'echarts/extension/bmap/bmap';
import { GetAreaRgPoint, GetRecordRgData, GetAreaRgPointByLine } from "@/services/ArtificialGrid/ArtificialGrid.js";
import { BMPGL } from "@/utils/bmpgl.js";
import { getDotPicIcon } from "@/utils/getDotPic.js";
import { styleJson } from "@/utils/mapStyle.js"
export default {
data () {
return {
dataArea1: require('@/assets/img/data_area1.png'),
dataArea2: require('@/assets/img/data_area2.png'),
spanTitle: "积分场强",
spanRightTitle: "方案一",
typeNumber: 1,
myChart: null,
zoom: 15,
dataArea1: require('@/assets/img/data_area1.png'),
dataArea2: require('@/assets/img/data_area2.png'),
ak: "GVelNGs7fvSLFlcssQrxVPpKSvdUHFIH",
type: 10,
markerList: [],
ArtificialGridData: [],
map: null,
myChart: null,
polyline: {
editing: false,
paths: [],
polylinePath: [],
map: {}
},
artificObj: {
spanRightTitleMi: '500*500',
isShowArtificialAndDefault: true,
startDot: null,
endDot: null,
startObj: null,
endObj: null,
len: 500,
zoom: 14,
}
}
},
mounted () {
this.getInit(this.type)
},
watch: {
typeNumber () {
this.getInit(this.type)
}
},
methods: {
async getInit (type) {
var _this = this
BMPGL(this.ak).then(async (BMapGL) => {
_this.map = new BMapGL.Map("allmap");
var scaleCtrl = new BMapGL.ScaleControl({ anchor: BMAP_ANCHOR_TOP_LEFT }); // 添加比例尺控件
// var zoomCtrl = new BMapGL.ZoomControl({ anchor: BMAP_ANCHOR_TOP_LEFT }); // 添加缩放控件
_this.map.addControl(scaleCtrl);
// _this.map.addControl(zoomCtrl);
const res = await GetAreaRgPoint({ type });
_this.ArtificialGridData = res.data
_this.ArtificialGridData.map(item => {
var polyline = new BMapGL.Polyline([
new BMapGL.Point(item.point1[0], item.point1[1]),
new BMapGL.Point(item.point2[0], item.point2[1]),
], { strokeColor: "blue", strokeWeight: 2, strokeOpacity: 0.5 });//创建折线
//添加覆盖物
function add_overlay () {
_this.map.addOverlay(polyline); //增加折线
}
add_overlay();
});
const resAddPoint = await GetRecordRgData({ type });
_this.markerList = resAddPoint.data
_this.markerList?.map(item => {
var png = getDotPicIcon(_this.typeNumber, item);
var myIcon = new BMapGL.Icon(png, new BMapGL.Size(10, 10));
var marker = new BMapGL.Marker(new BMapGL.Point(item.jd, item.wd), { icon: myIcon }); // 创建点
function add_point () {
_this.map.addOverlay(marker); //增加点
}
add_point();
var opts1 = {
width: 200,
height: 80,
};
var opts2 = {
width: 248,
height: 80,
};
var content1 = `
<div class='content-box'>
<div>人工测量点积分场强:<span class='etotal'>${item.etotal}</span></div>
<div>区域测量积分场强: <span class='enormal'>${(item.etotalRg.toFixed(2))}</span></div>
</div>
`
var content2 = `
<div class='content-box'>
<div>人工测量点电场强度占标率:<span class='etotal'>${item.enormal.toFixed(2) + '%'}</span></div>
<div>区域测量电场强度占标率: <span class='enormal'>${(item.enormalRg).toFixed(2) + '%'}</span></div>
</div>
`
var infoWindow = new BMapGL.InfoWindow(_this.typeNumber === 1 ? content1 : content2, _this.typeNumber === 1 ? opts1 : opts2);
var point = new BMapGL.Point(item.jd, item.wd);
// 点标记添加点击事件
marker.addEventListener('click', function () {
_this.map.openInfoWindow(infoWindow, point); // 开启信息窗口
});
})
var point = new BMapGL.Point(114.381294, 30.622897);
_this.map.centerAndZoom(point, _this.zoom);
// 删除覆盖物
_this.myChart = _this.map
_this.map.enableScrollWheelZoom();
})
},
handleCommand (val) {
this.spanRightTitle = val === 1 ? "方案一" : '方案二'
this.spanRightTitle === '方案一' ? this.getInit(10) : this.getInit(5);
},
handler ({ BMap, map }) {
let _this = this
this.polyline.map = map
},
clearGrid () {
this.map.clearOverlays()
this.polyline.paths = [];
this.artificObj.startDot = "";
this.artificObj.endDot = "";
this.artificObj.spanRightTitleMi = "500*500";
this.polyline.polylinePath = [];
},
changeArtificialGrid (_this) {
// this.artificObj.isShowArtificialAndDefault = !this.artificObj.isShowArtificialAndDefault
this.myChart && this.myChart.clearOverlays();
if (this.artificObj.isShowArtificialAndDefault) {
this.artificObj.isShowArtificialAndDefault = false;
this.artificObj.spanRightTitleMi = "500*500";
} else {
this.artificObj.isShowArtificialAndDefault = true;
this.getInit(this.type)
}
},
toggle (name) {
this[name].editing = !this[name].editing
},
syncPolyline (e) {
if (!this.polyline.editing) {
return
}
const { paths } = this.polyline
if (!paths.length) {
return
}
const path = paths[paths.length - 1]
if (!path.length) {
return
}
if (path.length === 1) {
path.push(e.point)
}
this.$set(path, path.length - 1, e.point)
},
newPolyline (e) {
if (!this.polyline.editing) {
return
}
const { paths } = this.polyline
if (!paths.length) {
paths.push([])
}
const path = paths[paths.length - 1]
path.pop()
if (path.length) {
paths.push([])
}
},
paintPolyline (e) {
if (!this.polyline.editing) {
return
}
const { paths } = this.polyline
!paths.length && paths.push([])
paths[paths.length - 1].push(e.point)
let res = this.polyline.paths[0];
this.artificObj.startDot = res.length >= 0 ? `${(res[0].lng).toFixed(4)} , ${(res[0].lat).toFixed(4)}` : "";
this.artificObj.endDot = res.length > 1 ? `${(res[1].lng).toFixed(4)} , ${(res[1].lat).toFixed(4)}` : "";
this.artificObj.startObj = res[0]
this.artificObj.endObj = res[1];
},
// 绘制网格
async paintGrid () {
// if (this.polyline.paths.length == 0) return
if (!this.polyline.editing) {
return this.$message({
message: '请先点击开始绘制',
type: 'warning'
});
}
console.log(this.artificObj.endDot);
if (!this.artificObj.startDot && !this.artificObj.endDot || this.artificObj.endDot == '') {
return this.$message({
message: '请选择起始点和结束点',
type: 'warning'
});
}
const { data } = await GetAreaRgPointByLine({
jd: this.artificObj.startObj.lng,
wd: this.artificObj.startObj.lat,
jd_end: this.artificObj.endObj.lng,
wd_end: this.artificObj.endObj.lat,
len: this.artificObj.spanRightTitleMi == "500*500" ? 500 : 1000
})
this.polyline.polylinePath = data;
this.polyline.paths = []
},
handleCommandMClick (val) {
console.log(val);
switch (val) {
case 3:
this.artificObj.spanRightTitleMi = "500*500";
this.artificObj.len = 500;
break;
case 4:
this.artificObj.spanRightTitleMi = "1000*1000";
this.artificObj.len = 1000
break;
}
},
handleCommandTitle (val) {
this.typeNumber = val
this.spanTitle = val === 1 ? "积分场强" : '电场强度占标率'
},
}
}
</script>
<style lang="less" scoped>
.map-box {
width: 100%;
height: 78vh;
}
.trajectory-chart-box {
position: relative;
img {
-webkit-user-drag: none;
position: absolute;
right: -20px;
bottom: 20px;
}
.box-card {
min-height: 88vh;
.artificial-issuee {
display: flex;
/deep/.el-dropdown {
width: 116px;
height: 28px;
line-height: 28px;
background: #f2f3f5;
border-radius: 2px;
}
}
.shadow-box {
z-index: 999999999;
width: 140px;
height: 78vh;
position: absolute;
right: 20px;
bottom: -10px;
margin-bottom: 30px;
box-sizing: border-box;
background: linear-gradient(
270deg,
#d9d9d9 0%,
rgba(217, 217, 217, 0) 162.68%
);
.scheme-box {
/deep/.el-input {
font-size: 12px;
color: #666;
}
span {
display: inline-block;
margin: 10px;
font-size: 14px;
font-weight: bold;
color: #000;
}
b {
font-weight: none;
}
p {
margin-left: 5px;
font-size: 10px;
letter-spacing: -0.0807688px;
color: #ff0000;
}
}
}
}
}
.scheme-box {
/deep/.el-dropdown {
background: #f2f3f5;
}
}
/deep/.el-icon--right {
margin-left: 25px;
}
/deep/.el-input__inner {
height: 30px;
width: 116px;
margin-left: 10px;
padding: 0 !important;
padding-left: 5px !important;
}
</style>
实际截图
image.png六.固定 折线图的X轴和Y轴数据
<template>
<div>
<div class="pop-box"
v-if="resStatus == 200">
<el-button size="mini"
type="primary"
@click="backGo">返回</el-button>
<el-row class="t-a-c">
<el-col :span="12">
<div>
<span>最小频率:</span>
<span class="show-style">{{ this.detailObj && this.detailObj.minFreq || "" }}</span>
<span class="f-c-0">MHz</span>
</div>
</el-col>
<el-col :span="12">
<div>
<span>最大频率:</span>
<span class="show-style">{{ this.detailObj && this.detailObj.maxFreq || "" }}</span>
<span class="f-c-0">MHz</span>
</div>
</el-col>
</el-row>
<el-row class="t-a-c m-t-10">
<el-col :span="12">
<div style="margin-left:-5px;">
<span>积分场强:</span>
<span class="show-style">{{ deviceguid.etotal || "" }}</span>
<span class="f-c-0">V/m</span>
</div>
</el-col>
<el-col :span="12">
<div style="margin-left:-60px;">
<span>电场强度占标率:</span>
<span class="show-style">{{ deviceguid.enormal || "" }}</span>
<span class="f-c-0">%</span>
</div>
</el-col>
</el-row>
<div class="com-chart"
id="main"
style="max-width: 100%;min-height: 50vh;"></div>
</div>
<div class="pop-box"
v-else>
<el-result icon="warning"
title="该位置无频谱测量数据"
subTitle="">
<template slot="extra">
<el-button size="mini"
type="primary"
@click="backGo">返回</el-button>
</template>
</el-result>
</div>
</div>
</template>
<script>
import { GetListByDeviceguid } from "@services/Track/Track.js";
import * as echarts from 'echarts';
export default {
data () {
return {
detailObj: "",
resStatus: 200
}
},
props: {
deviceguid: {
type: Object,
default () {
return {}
}
},
type: {
type: Number,
default: 1
}
},
mounted () {
this.getData();
},
methods: {
backGo () {
this.$emit("backIshow")
},
async getData () {
const res = await GetListByDeviceguid({ deviceguid: this.deviceguid.deviceguid });
this.resStatus = res.code
if (res.code === 500) {
return ""
}
this.detailObj = res.data
this.initChart(res.data.data)
},
initChart (data) {
let chartDom = document.getElementById('main');
let myChart = echarts.init(chartDom);
let option = {
tooltip: {
trigger: 'item',
formatter: (params) => {
console.log();
let templete = '';
if (params.seriesType === 'line') {
templete = '频率: ' + params.data[0] + '<br />' + "积分场强: " + params.data[1]
}
return templete
},
},
grid: {
containLabel: true,
top: '8%',
left: '3%',
right: '8%',
bottom: '5%',
show: true,
backgroundColor: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(8,20,48,0.9)"
},
{
offset: 1,
color: "rgba(8,20,48,0.9)"
}
]),
borderColor: "rgba(8,20,48)"
},
xAxis: {
name: '/MHz',
type: 'value',
interval: 2999.95, // 步长
min: 0.1, // 起始
max: 6000, // 终止
splitLine: {
show: true,
lineStyle: {
type: "solid",
color: " #334984",
},
},
},
yAxis: {
name: 'V/m',
type: 'log',
min: 0.00001,
max: 100,
logBase: 10,
splitLine: {
lineStyle: {
color: " #334984",
}
},
},
series: [
{
type: 'line',
data: data
}
]
};
option && myChart.setOption(option);
window.addEventListener('resize', function () {
myChart.resize();
});
}
}
}
</script>
<style scoped lang="less">
/deep/.el-button--primary {
color: #fff;
background-color: #3f85fb;
border-color: #409eff;
}
.show-style {
display: inline-block;
width: 95px;
height: 32px;
line-height: 32px;
background: #f2f3f5;
border-radius: 2px;
margin: 0 3px;
}
.com-chart {
margin-top: 10px;
margin-left: 15px;
}
</style>