<template>
|
<div class="heatCamera">
|
<div class="camera">
|
<nav class="header-nav">
|
<div class="logo">
|
<img src="image/basic.png" alt />
|
</div>
|
<div class="toolbar">
|
<el-radio-group v-model="dimension" size="mini">
|
<el-radio-button :label="1">热力图</el-radio-button>
|
<el-radio-button :label="2">轨迹图</el-radio-button>
|
</el-radio-group>
|
<el-select
|
v-model="camera"
|
filterable
|
size="mini"
|
style="width:200px;"
|
placeholder="请选择摄像机"
|
value-key="id"
|
>
|
<el-option
|
v-for="item in allCameras"
|
style="font-size:12px"
|
:key="item.id"
|
:label="item.name"
|
:value="item"
|
:title="item.name"
|
></el-option>
|
</el-select>
|
|
<el-date-picker
|
v-model="timeRange"
|
value-format="yyyy-MM-dd HH:mm:ss"
|
type="datetimerange"
|
range-separator="至"
|
start-placeholder="开始日期"
|
end-placeholder="结束日期"
|
size="mini"
|
></el-date-picker>
|
<el-button
|
type="primary"
|
@click="postCameraData"
|
:loading="querying"
|
size="mini"
|
icon="el-icon-search"
|
>查询</el-button>
|
</div>
|
</nav>
|
|
<div class="img-area" ref="heatMap">
|
<span
|
class="dot"
|
v-for="(item,index) in dots"
|
:style="{top:item.y+'px',left: item.x+'px'}"
|
:key="'d'+index"
|
></span>
|
<el-image :src="baseImg" fit="contain" ref="img">
|
<div slot="error" class="image-slot"></div>
|
</el-image>
|
</div>
|
</div>
|
</div>
|
</template>
|
<script>
|
import Heatmap from 'heatmap.js';
|
import { getHeatCameraData } from '@/api/heatCamera'
|
import { getCamerasByServer } from '@/api/pollConfig'
|
import { getPersonData } from './api'
|
|
export default {
|
name: "heatCamera",
|
computed: {
|
baseImg() {
|
let imgUrl = "";
|
|
if (this.camera.snapshot_url && this.camera.snapshot_url.length) {
|
imgUrl = '/httpImage/' + this.camera.snapshot_url
|
}
|
|
return imgUrl
|
}
|
},
|
data() {
|
return {
|
publicPath: process.env.BASE_URL,
|
querying: false,
|
dots: [],
|
dimension: 1,
|
timeRange: [
|
this.$moment().format("YYYY-MM-DD 00:00:00"),
|
this.$moment().format("YYYY-MM-DD HH:mm:ss")
|
],
|
camera: {},
|
allCameras: [],
|
snapshot_url: "",
|
heatmapInstance: null,
|
}
|
},
|
mounted() {
|
this.getAllCamera();
|
},
|
methods: {
|
getAllCamera() {
|
getCamerasByServer().then(rsp => {
|
if (rsp && rsp.success) {
|
this.allCameras = rsp.data
|
}
|
})
|
},
|
setHeatmapData(sources) {
|
if (sources === null || sources.length < 1) {
|
return
|
}
|
var heatmapConfig = {
|
container: document.querySelector('.img-area'),
|
radius: 20,
|
maxOpacity: .55,
|
minOpacity: 0,
|
blur: .55,
|
gradient: {
|
'.8': 'yellow',
|
'0.95': 'rgba(251, 40, 40, 0.3)',
|
'0.6': 'rgba(42, 251, 199, 0.3)',
|
//'0.5': 'rgba(2, 119, 251, 0.3)'
|
'0.5': 'rgba(2, 251, 251, 0.3)'
|
}
|
};
|
var points = {
|
max: 300,
|
min: 0,
|
data: []
|
}
|
if (this.heatmapInstance === null) {
|
this.heatmapInstance = Heatmap.create(heatmapConfig);
|
} else {
|
this.heatmapInstance.setData(points);
|
}
|
sources.forEach(ele => {
|
points.data.push(this.formatPoint(ele))
|
if (this.dimension == 2) {
|
this.dots.push(this.formatPoint(ele))
|
}
|
});
|
|
//热力图
|
if (this.dimension == 1) {
|
this.heatmapInstance.setData(points);
|
}
|
},
|
postCameraData() {
|
this.dots = [];
|
let params = {};
|
if (!this.camera.id || !this.camera.id.length) {
|
this.$message({
|
type: "error",
|
message: "请选择一个摄像机"
|
})
|
return;
|
}
|
params.cameraIds = [this.camera.id];
|
params.startDate = this.timeRange[0];
|
params.endDate = this.timeRange[1];
|
|
this.querying = true;
|
getPersonData(params).then(rsp => {
|
if (rsp && rsp.success) {
|
this.setHeatmapData(rsp.data.result)
|
}
|
this.querying = false
|
}).catch(() => {
|
this.querying = false
|
})
|
},
|
formatPoint(data) {
|
var converters = {
|
"default": {
|
"scale": 0.66,
|
"offsetX": 0,
|
"offsetY": 0
|
}
|
}
|
|
var cv = converters[data.cameraId] ? converters[data.cameraId] : converters["default"]
|
|
var topLeft = data.personRect.topLeft
|
var bottomRight = data.personRect.bottomRight
|
|
// 中心点
|
var dataPoint = {
|
//x: ((topLeft.x + bottomRight.x) * cv.scale + cv.offsetX * 2) / 2,
|
//y: ((topLeft.y + bottomRight.y) * cv.scale + cv.offsetY * 2) / 2,
|
x: ((topLeft.x + bottomRight.x) * cv.scale + cv.offsetX * 2) / 2,
|
y: ((bottomRight.y) * cv.scale + cv.offsetY),
|
value: data.stayTime
|
};
|
if (dataPoint.y > 720) {
|
dataPoint.y = 720
|
}
|
|
return dataPoint
|
}
|
|
}
|
}
|
</script>
|
<style lang="scss">
|
.heatCamera {
|
width: 100%;
|
height: 100%;
|
background: #e9ebf2;
|
.header-nav {
|
height: 60px;
|
min-width: 1200px;
|
background-image: linear-gradient(-180deg, #ffffff 13%, #e9ebf2 100%);
|
}
|
.toolbar {
|
width: 850px;
|
height: 60px;
|
//background: rgba(0,0,0,.3);
|
position: absolute;
|
right: 60px;
|
top: 20px;
|
text-align: center;
|
line-height: 60px;
|
z-index: 10;
|
.el-date-editor {
|
vertical-align: middle;
|
border-radius: 4px 0 0 4px;
|
margin: 0 8px;
|
}
|
.el-button {
|
vertical-align: middle;
|
margin-left: 4px;
|
}
|
}
|
.img-area {
|
margin: 30px auto;
|
width: 1280px;
|
height: 720px;
|
position: relative;
|
font-size: 0;
|
background-color: black;
|
.dot {
|
width: 10px;
|
height: 10px;
|
background-image: radial-gradient(circle, #04f3ff, #adf7f7, #31e4d3);
|
opacity: 0.5;
|
border-radius: 50%;
|
position: absolute;
|
z-index: 1000;
|
}
|
}
|
img {
|
display: block;
|
}
|
}
|
</style>
|