<template>
|
<div
|
ref="content"
|
class="content"
|
>
|
<div class="formInBox ">
|
<el-form
|
:inline="true"
|
:model="formInline"
|
>
|
<el-form-item>
|
<el-radio-group
|
v-model="formInline.pollutant"
|
size="small"
|
@input="getPollutant"
|
>
|
<el-radio-button
|
v-for="item in sensorArr"
|
:key="item.code"
|
:label="item.name"
|
/>
|
</el-radio-group>
|
</el-form-item>
|
<el-form-item>
|
<!-- <el-select
|
v-model="orgId"
|
size="small"
|
placeholder="请选择"
|
@change="regionData"
|
>
|
<el-option
|
v-for="item in orgData"
|
:key="item.id"
|
:label="item.name"
|
:value="item.id"
|
/>
|
</el-select> -->
|
<el-cascader
|
v-model="orgId"
|
size="small"
|
:options="orgData"
|
:props="props"
|
clearable
|
@change="regionData"
|
/>
|
</el-form-item>
|
<el-form-item>
|
<el-radio-group
|
v-model="formInline.dateRadio"
|
size="small"
|
>
|
<el-radio-button label="小时" />
|
<el-radio-button label="天" />
|
<el-radio-button label="月" />
|
</el-radio-group>
|
</el-form-item>
|
<el-form-item>
|
<selectHour
|
:data-type="dataType"
|
@selectHourData="selectHourData"
|
/>
|
</el-form-item>
|
<el-form-item>
|
<el-button
|
type="primary"
|
size="small"
|
@click="onSubmit"
|
>
|
查询
|
</el-button>
|
<el-button
|
type="primary"
|
size="small"
|
@click="download"
|
>
|
截图
|
</el-button>
|
</el-form-item>
|
</el-form>
|
</div>
|
<div id="mapd" />
|
<div class="timeLine">
|
<div
|
:style="{ background: 'url(' + selectSensor.src + ') no-repeat' }"
|
class="buttomColorLine"
|
/>
|
<Main
|
v-if="dateTimes.length > 0"
|
:options="options"
|
:date-times="dateTimes"
|
:date-type="formInline.dayType"
|
@getDateFun="getDateFun"
|
/>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
// import dayjs from 'dayjs'
|
import _ from 'lodash'
|
import selectHour from './components/selectHour.vue'
|
import Main from './components/timeLinePlay.vue'
|
import html2canvas from 'html2canvas'
|
export default {
|
components: { selectHour, Main },
|
data () {
|
return {
|
map: null,
|
heatmap: null,
|
markerClusterer: null,
|
orgData: [],
|
props: { checkStrictly: true, label: 'name', value: 'id', children: 'children' },
|
orgId: [],
|
city: '苏州',
|
formInline: {
|
city: '',
|
cityCode: '',
|
dayType: 'hour',
|
starTime: '',
|
endTime: '',
|
dateRadio: '小时',
|
pollutant: 'PM10',
|
},
|
selectSensor: {code: 'a34002',
|
name: 'PM10',
|
maxNumber: 500,
|
src: require('@/assets/images/tl_PM10.png'),
|
gradient: {
|
0: '#12a112',
|
0.1: '#12a112',
|
0.3: '#feff01',
|
0.5: '#fd8200',
|
0.7: '#fd0001',
|
0.84: '#95014b',
|
1: '#7e0226'
|
}},
|
sensorArr: [
|
{ code: 'a34002',
|
name: 'PM10',
|
maxNumber: 500,
|
src: require('@/assets/images/tl_PM10.png'),
|
gradient: {
|
0: '#12a112',
|
0.1: '#12a112',
|
0.3: '#feff01',
|
0.5: '#fd8200',
|
0.7: '#fd0001',
|
0.84: '#95014b',
|
1: '#7e0226'
|
}},
|
{ code: 'a34004',
|
name: 'PM2.5',
|
maxNumber: 350,
|
src: require('@/assets/images/tl_PM2.5.png'),
|
gradient: {
|
0: '#12a112',
|
0.1: '#12a112',
|
0.21: '#feff01',
|
0.32: '#fd8200',
|
0.42: '#fd0001',
|
0.71: '#95014b',
|
1: '#7e0226'
|
} },
|
{ code: 'a21026',
|
name: 'SO2',
|
maxNumber: 150,
|
src: require('@/assets/images/tl_SO2.png'),
|
gradient: {
|
1: '#feff01',
|
0.3: '#12a112',
|
}
|
},
|
{ code: 'a21004',
|
name: 'NO2',
|
maxNumber: 400,
|
src: require('@/assets/images/tl_NO2.png'),
|
gradient: {
|
0: '#12a112',
|
0.1: '#12a112',
|
0.15: '#feff01',
|
0.19: '#feff01',
|
0.20: '#fd8200',
|
0.25: '#fd8200',
|
0.45: '#fd8200',
|
0.5: '#fd0001',
|
0.7: '#95014b',
|
1: '#7e0226'
|
}},
|
{ code: 'a21005',
|
name: 'CO',
|
maxNumber: 48,
|
src: require('@/assets/images/tl_CO.png'),
|
gradient: {
|
0.0: '#12a112',
|
0.04: '#12a112',
|
0.083: '#feff01',
|
0.29: '#fd8200',
|
0.5: '#fd0001',
|
0.75: '#95014b',
|
1: '#7e0226'
|
}},
|
{ code: 'a05024',
|
name: 'O3',
|
maxNumber: 500,
|
src: require('@/assets/images/tl_O3.png'),
|
gradient: {
|
0: '#12a112',
|
0.32: '#12a112',
|
0.33: '#feff01',
|
0.4: '#feff01',
|
0.41: '#fd8200',
|
0.6: '#fd8200',
|
0.61: '#fd0001',
|
0.8: '#fd0001',
|
0.9: '#95014b',
|
1: '#7e0226'
|
} },
|
{ code: 'a99054',
|
name: 'TVOC',
|
maxNumber: 4,
|
src: require('@/assets/images/tl_TVOCNew.png'),
|
gradient: {
|
0: '#12a112',
|
0.12: '#12a112',
|
0.25: '#feff01',
|
0.375: '#fd8200',
|
0.5: '#fd0001',
|
0.75: '#95014b',
|
1: '#7e0226'
|
}}
|
],
|
heatMapData: [],
|
dataType: 'datetimerange',
|
options: {
|
speed: 2
|
},
|
polygon: null,
|
districtSearch: null,
|
dateTimes: [],
|
activeItem: {},
|
markerList: []
|
}
|
},
|
watch: {
|
'formInline.dateRadio': {
|
handler: function (newVal, oldVal) {
|
if (newVal === '小时') {
|
this.dataType = 'datetimerange'
|
this.formInline.dayType = 'hour'
|
this.dateTimes = []
|
} else if (newVal === '天') {
|
this.dataType = 'daterange'
|
this.dateTimes = []
|
this.formInline.dayType = 'day'
|
} else if (newVal === '月') {
|
this.dataType = 'monthrange'
|
this.dateTimes = []
|
this.formInline.dayType = 'month'
|
}
|
},
|
deep: true
|
},
|
// 'formInline.city': {
|
// handler: function (newVal, oldVal) {
|
// console.log('newVal', newVal === '')
|
// if (newVal !== '') {
|
// this.init1()
|
// if (!!this.formInline.starTime && !!this.formInline.endTime) {
|
// this.onSubmit()
|
// }
|
// }
|
// },
|
// deep: true
|
// },
|
activeItem: {
|
handler (newVal, oldVal) {
|
|
},
|
deep: true
|
}
|
},
|
created () {
|
},
|
mounted () {
|
// let dataTime = dayjs().format('YYYY-MM-DD')
|
this.getOrganizationId()
|
// this.getData(`${dataTime} 00`)
|
},
|
|
destroyed () {
|
if (this.map) {
|
this.map.destroy()
|
}
|
},
|
methods: {
|
download () {
|
const ref = this.$refs.content // 截图区域
|
html2canvas(ref, {
|
backgroundColor: '#e8f4ff',
|
useCORS: true // 如果截图的内容里有图片,可能会有跨域的情况,加上这个参数,解决文件跨域问题
|
}).then((canvas) => {
|
const dataURL = canvas.toDataURL('image/png')
|
const creatDom = document.createElement('a')
|
document.body.appendChild(creatDom)
|
creatDom.href = dataURL
|
creatDom.download = '图片'
|
creatDom.click()
|
})
|
},
|
getDateFun (item) {
|
console.log(item)
|
this.activeItem = item
|
if (this.orgId.length > 0) {
|
this.getData(item.name)
|
}
|
},
|
getPollutant (data) {
|
this.selectSensor = _.find(this.sensorArr, { name: data })
|
this.dateTimes = []
|
if (this.heatmap) {
|
this.map.remove(this.heatmap)
|
this.heatmap = null
|
}
|
console.log('this.heatmap', this.heatmap)
|
},
|
// 初始化地图
|
initMap () {
|
let zoom = 10
|
if (this.formInline.cityCode === '320900') {
|
zoom = this.formInline.areName === 'dafengqu' ? 15 : 13
|
}
|
var map = new AMap.Map('mapd', {
|
resizeEnable: true,
|
zoomEnable: false,
|
zoom: zoom
|
})
|
this.map = map
|
map.on('click', function (e) {
|
console.log('e.lnglat.getLng() + ', ' + e.lnglat.getLat()', e.lnglat.getLng() + ',' + e.lnglat.getLat())
|
})
|
this.init1()
|
// let that = this
|
},
|
init1 () { // 区域遮盖
|
var that = this
|
if (that.polygon) {
|
that.map.remove(that.polygon)
|
that.map.remove(that.districtSearch)
|
that.polygon = null
|
that.districtSearch = null
|
}
|
this.districtSearch = AMap.plugin('AMap.DistrictSearch', function () {
|
new AMap.DistrictSearch({
|
extensions: 'all',
|
subdistrict: 0
|
}).search(that.formInline.cityCode, function (status, result) { // 外多边形坐标数组和内多边形坐标数组
|
var outer = [
|
new AMap.LngLat(-360, 90, true),
|
new AMap.LngLat(-360, -90, true),
|
new AMap.LngLat(360, -90, true),
|
new AMap.LngLat(360, 90, true)
|
]
|
var pathArray = [outer]
|
let ycPoints = {
|
areas: [{ // 围栏1
|
rejectTexture: true, // 是否屏蔽自定义地图的纹理
|
path: [[
|
[120.06316306, 33.41753995999999],
|
[120.2617243421, 33.41753995999999],
|
[120.2617243421, 33.308387182],
|
[120.06316306, 33.308387182],
|
[120.06316306, 33.41753995999999]
|
]]
|
}]
|
}
|
|
var holes = result.districtList[0].boundaries
|
console.log('that.formInline', that.formInline)
|
if (that.formInline.cityCode === '320900') {
|
// 盐城
|
|
that.map.setCenter([120.16, 33.36])
|
if (that.formInline.areName === 'dafengqu') {
|
that.map.setCenter([120.435345, 33.203704])
|
ycPoints = {
|
areas: [{ // 围栏1
|
rejectTexture: true, // 是否屏蔽自定义地图的纹理
|
path: [[ [120.41615942, 33.215693],
|
[120.45416756599998, 33.215693],
|
[120.45416756599998, 33.192137742599996],
|
[120.41615942000003, 33.19213774259998],
|
[120.41615942, 33.215693] ]]
|
}]
|
}
|
}
|
pathArray.push.apply(pathArray, ycPoints.areas[0].path)
|
} else {
|
pathArray.push.apply(pathArray, holes)
|
that.map.setCity(that.formInline.city)
|
}
|
// pathArray.push.apply(pathArray, holes)
|
that.polygon = new AMap.Polygon({
|
pathL: pathArray,
|
strokeColor: 'red', // 城市边界颜色
|
strokeWeight: 3,
|
fillColor: '#ccc', // 遮罩背景色黑色
|
fillOpacity: 1
|
})
|
that.polygon.setPath(pathArray)
|
that.map.add(that.polygon)
|
})
|
})
|
},
|
getData (newVal) {
|
this.$request({
|
url: '/heatMap/query',
|
method: 'get',
|
params: {
|
id: this.orgId[0],
|
startTime: newVal,
|
type: this.selectSensor.code,
|
form: this.formInline.dayType
|
}
|
})
|
.then(res => {
|
if (res.data !== '0') {
|
if (this.heatmap === null) {
|
this.createHeatMap()
|
}
|
this.heatMapData = res.data
|
this.dataProcessing(this.heatMapData)
|
this.heatmap.setDataSet({
|
data: this.heatMapData,
|
max: this.selectSensor.maxNumber
|
})
|
} else {
|
this.map.remove(this.heatmap)
|
this.heatmap = null
|
}
|
})
|
.catch(err => {
|
console.log(err)
|
})
|
},
|
dataProcessing (heatMapData) {
|
// 获取最大值
|
console.log('this.heatMapData', this.heatMapData)
|
const max = heatMapData.reduce((prev, current) => (prev.count > current.count ? prev : current)).count
|
|
// so2
|
if (this.selectSensor.code === 'a21026') {
|
if (max > 150 && max <= 475) {
|
this.selectSensor.maxNumber = 475
|
this.heatmap.setOptions({
|
gradient: {
|
0.1: '#12a112',
|
0.2: '#feff01',
|
0.3: '#feff01',
|
0.32: '#fd8200',
|
0.4: '#fd8200',
|
1: '#fd8200'
|
}
|
})
|
}
|
if (max > 475 && max <= 1000) {
|
this.selectSensor.maxNumber = 1000
|
this.heatmap.setOptions({
|
gradient: {
|
0: '#12a112',
|
0.05: '#12a112',
|
0.15: '#feff01',
|
0.47: '#fd8200',
|
0.5: '#fd0001',
|
0.8: '#fd0001',
|
0.9: '#95014b',
|
1: '#7e0226'
|
}
|
})
|
}
|
} else if (this.selectSensor.code === 'a05024') {
|
if (max > 150 && max <= 475) {}
|
}
|
},
|
// 聚合点
|
setMarkers (curData) {
|
curData.forEach((item, index) => {
|
let div = document.createElement('div')
|
let bgColor = 'hsla(180, 100%, 50%, 0.7)'
|
let fontColor = '#000'
|
let borderColor = 'hsl(180, 100%, 40%)'
|
let shadowColor = 'hsl(180, 100%, 50%)'
|
div.id = 'pint' + index
|
div.style.backgroundColor = bgColor
|
let size = 40
|
div.style.width = div.style.height = size + 'px'
|
div.style.border = 'solid 1px ' + borderColor
|
div.style.borderRadius = size / 2 + 'px'
|
div.style.boxShadow = '0 0 1px ' + shadowColor
|
div.innerHTML = Math.floor(Number(item.count))
|
div.style.lineHeight = size + 'px'
|
div.style.color = fontColor
|
div.style.fontSize = '14px'
|
div.style.textAlign = 'center'
|
let marker = new AMap.Marker({
|
position: [item.lng, item.lat],
|
title: item.name,
|
extData: Math.floor(Number(item.count)),
|
anchor: 'center',
|
// 将 html 传给 content
|
content: div,
|
// 以 icon 的 [center bottom] 为原点
|
offset: new AMap.Pixel(3, 10)
|
})
|
this.markerList.push(marker)
|
})
|
this.map.add(this.markerList)
|
var count = this.markerList.length
|
// eslint-disable-next-line no-new
|
if (this.markerClusterer) {
|
this.markerClusterer.clearMarkers()
|
}
|
let that = this
|
AMap.plugin('AMap.MarkerClusterer', function () {
|
that.markerClusterer = new AMap.MarkerClusterer(that.map, that.markerList, {
|
gridSize: 100,
|
renderClusterMarker: function (context) {
|
let contNumber = 0
|
context.markers.forEach((item, index) => {
|
console.log('indexitem', index, item.getExtData())
|
contNumber += item.getExtData()
|
})
|
console.log('contNumber', contNumber)
|
let factor = Math.pow(context.count / count, 1 / 18)
|
let div = document.createElement('div')
|
let Hue = 180 - factor * 180
|
let bgColor = 'hsla(' + Hue + ',100%,50%,0.7)'
|
let fontColor = 'hsla(' + Hue + ',100%,20%,1)'
|
let borderColor = 'hsla(' + Hue + ',100%,40%,1)'
|
let shadowColor = 'hsla(' + Hue + ',100%,50%,1)'
|
div.style.backgroundColor = bgColor
|
let size = Math.round(30 + Math.pow(context.count / count, 1 / 5) * 20)
|
div.style.width = div.style.height = size + 'px'
|
div.style.border = 'solid 1px ' + borderColor
|
div.style.borderRadius = size / 2 + 'px'
|
div.style.boxShadow = '0 0 1px ' + shadowColor
|
div.innerHTML = contNumber
|
div.style.lineHeight = size + 'px'
|
div.style.color = fontColor
|
div.style.fontSize = '14px'
|
div.style.textAlign = 'center'
|
context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2))
|
context.marker.setContent(div)
|
console.log('context.marker----------------', context.marker)
|
}
|
})
|
})
|
},
|
getDayListData () {
|
this.$request({
|
url: '/heatMap/queryTime',
|
method: 'get',
|
params: {
|
type: this.formInline.dayType,
|
startTime: this.formInline.starTime,
|
endTime: this.formInline.endTime,
|
}
|
})
|
.then(res => {
|
this.dateTimes = res.data
|
})
|
.catch(err => {
|
console.log(err)
|
})
|
},
|
getOrganizationId () {
|
this.$request({
|
url: '/organization/getOrganizationId',
|
method: 'get'
|
})
|
.then(res => {
|
this.orgData = res.data.map(item => {
|
if (item.id === 73) {
|
item.children = [{
|
id: 'shiqu',
|
name: '市区'
|
}, {
|
id: 'dafengqu',
|
name: '大丰区'
|
}]
|
}
|
return item
|
})
|
})
|
.catch(err => {
|
console.log(err)
|
})
|
},
|
createHeatMap () {
|
let that = this
|
let radius = this.formInline.areName === 'shiqu' ? 100 : 100
|
console.log('radius', radius)
|
this.map.plugin(['AMap.Heatmap'], function () {
|
// 初始化heatmap对象
|
that.heatmap = new AMap.Heatmap(that.map, {
|
radius: radius, // 给定半径
|
opacity: [0.5, 1],
|
gradient: that.selectSensor.gradient
|
})
|
})
|
},
|
|
onSubmit () {
|
if (!!this.formInline.city && !!this.formInline.starTime && !!this.formInline.endTime) {
|
// this.map.clearMap()
|
|
this.getDayListData()
|
|
if (this.map) {
|
this.map.destroy()
|
}
|
this.initMap()
|
this.createHeatMap()
|
this.getData(this.formInline.starTime)
|
// this.map.setZoom(12)
|
} else {
|
this.$message({
|
showClose: true,
|
duration: 2000,
|
message: '请选择区域或者时间!',
|
type: 'error'
|
})
|
}
|
},
|
regionData (id) {
|
console.log('id', id)
|
let cityData = _.find(this.orgData, { id: id[0] })
|
if (id[0] === 73) {
|
if (id[1]) {
|
this.formInline.areName = id[1]
|
}
|
this.formInline.city = cityData.cityName
|
this.formInline.cityCode = String(cityData.cityCode)
|
} else {
|
this.formInline.city = cityData.areaName
|
this.formInline.cityCode = String(cityData.areaCode)
|
}
|
},
|
selectHourData (data) {
|
console.log('ccccc', this.formInline)
|
if (data) {
|
this.formInline.starTime = data[0]
|
this.formInline.endTime = data[1]
|
if (this.formInline.city) {
|
this.getDayListData()
|
}
|
} else {
|
this.formInline.starTime = ''
|
this.formInline.endTime = ''
|
}
|
},
|
}
|
}
|
</script>
|
|
<style scoped lang="scss">
|
.content{
|
width: 100%;
|
height: 100%;
|
position: relative;
|
.formInBox{
|
display: flex;
|
justify-content: flex-start;
|
align-items: center;
|
position: absolute;
|
padding: 5px 10px;
|
width: 100%;
|
z-index: 999;
|
background: rgba(204,204,204,0.5);
|
/deep/.el-form-item{
|
margin-bottom: 0px;
|
}
|
}
|
}
|
#mapd {
|
width: 100%;
|
height: 100%;
|
resize: both;
|
z-index: 0;
|
}
|
.timeLine{
|
position: absolute;
|
padding: 5px 10px;
|
bottom: 5px;
|
width: 100%;
|
z-index: 999;
|
.buttomColorLine{
|
height: 50px;
|
}
|
}
|
/deep/.menu-icon {
|
font-size: 20px;
|
width: 30px;
|
height: 30px;
|
background-size: cover;
|
background-repeat: no-repeat;
|
display: inline-block;
|
background-image: url('./components/img/round.png');
|
}
|
/deep/.menu-font{
|
font-size: 16px;
|
text-align: center;
|
max-width: 120px;
|
}
|
/deep/.amap-logo,/deep/.amap-copyright{
|
display: none!important;
|
}
|
</style>
|