| | |
| | | <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"> |
| | | <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 |
| | | @change="timeChange" |
| | | 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">查询</el-button> |
| | | <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="`${publicPath}images/login-net.png`" fit="contain" ref="img"></el-image> |
| | | <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> |
| | | Date.prototype.Format = function (fmt) { |
| | | var o = { |
| | | "M+": this.getMonth() + 1, //月份 |
| | | "d+": this.getDate(), //日 |
| | | "H+": this.getHours(), //小时 |
| | | "m+": this.getMinutes(), //分 |
| | | "s+": this.getSeconds(), //秒 |
| | | "q+": Math.floor((this.getMonth() + 3) / 3), //季度 |
| | | "S": this.getMilliseconds() //毫秒 |
| | | }; |
| | | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); |
| | | for (var k in o) |
| | | if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); |
| | | return fmt; |
| | | } |
| | | 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: [new Date(2020, 7, 23, 8), new Date()], |
| | | params: { |
| | | cameraIds: ["ba8c1624-55a7-4f20-9c54-01e56448aeb5"], |
| | | startDate: new Date(2020, 7, 23, 8).Format("yyyy-MM-dd HH:mm:ss"), |
| | | endDate: new Date().Format("yyyy-MM-dd HH:mm:ss"), |
| | | //thresholdTime: 100, |
| | | }, |
| | | 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 () { |
| | | console.log(Heatmap.create) |
| | | |
| | | this.getAllCamera(); |
| | | }, |
| | | methods: { |
| | | timeChange(val) { |
| | | this.params.startDate = val[0]; |
| | | this.params.endDate = val[1]; |
| | | getAllCamera() { |
| | | getCamerasByServer().then(rsp => { |
| | | if (rsp && rsp.success) { |
| | | this.allCameras = rsp.data |
| | | } |
| | | }) |
| | | }, |
| | | setHeatmapData(sources) { |
| | | if (sources === null || sources.length < 1) { |
| | |
| | | '.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, 119, 251, 0.3)' |
| | | '0.5': 'rgba(2, 251, 251, 0.3)' |
| | | } |
| | | }; |
| | | var points = { |
| | |
| | | }, |
| | | postCameraData() { |
| | | this.dots = []; |
| | | var xhr = new XMLHttpRequest(); |
| | | xhr.open('post', '/data/api-v/es/getPersonData'); |
| | | xhr.setRequestHeader('Content-Type', 'application/json'); |
| | | xhr.setRequestHeader('Authorization', 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjQ3NDUwMjU5MjMsInVzZXIiOiJ7XCJpZFwiOlwiZTZjY2QzNmQtNGYxNi00NmZjLTg4ZDUtMDczNjU4NjZkMjA1XCIsXCJwZXJtaXNzaW9uc1wiOltcInByb2R1Y3RNYW5nZTpwdWJsaXNoXCIsXCJjb2RlTWFuZ2U6dmlld1wiLFwiZGV2aWNlTWFuYWdlOmFkZFwiLFwiYWRtaW5NYW5hZ2VcIixcIm9yZGVyTWFuZ2VcIixcImRldmljZU1hbmFnZTp2aWV3XCIsXCJwcm9kdWN0TWFuZ2U6YWRkXCIsXCJhZG1pbk1hbmFnZTp2aWV3XCIsXCJjb2RlTWFuZ2U6YWRkXCIsXCJwcm9kdWN0TWFuZ2U6b2ZmU2FsZVwiLFwib3JkZXJNYW5nZTpjYW5jZWxcIixcInByb2R1Y3RDZW50ZXI6ZG93bmxvYWRcIixcInByb2R1Y3RDZW50ZXI6YnV5XCIsXCJwcm9kdWN0TWFuZ2U6dmlld1wiLFwiYXBpXCIsXCJob21lXCIsXCJvcmRlck1hbmdlOnBheVwiLFwiYWRtaW5NYW5hZ2U6YWRkXCIsXCJvcmRlck1hbmdlOmRvd25sb2FkXCIsXCJwcm9kdWN0Q2VudGVyXCIsXCJkZXZpY2VNYW5hZ2U6dW5iaW5kXCIsXCJvcmRlck1hbmdlOnZpZXdcIixcImFkbWluTWFuYWdlOmVkaXRcIixcImRldmljZU1hbmFnZVwiLFwidmlwTWFuYWdlOmFkZFwiLFwidmlwTWFuYWdlOnZpZXdcIixcInByb2R1Y3RDZW50ZXI6dmlld1wiLFwidmlwTWFuYWdlOmVkaXRcIixcInZpcE1hbmFnZVwiLFwicHJvZHVjdE1hbmdlOmVkaXRcIixcImNvZGVNYW5nZVwiLFwicHJvZHVjdE1hbmdlXCJdLFwidXNlcm5hbWVcIjpcImJhc2ljXCJ9In0.vwjAFkWuEyadRLvIOGK8LFE3MjpY3SQ7j6AlTXnQDG8'); |
| | | xhr.send(JSON.stringify(this.params)); |
| | | xhr.onload = function () { |
| | | if (xhr.readyState == 4) { |
| | | var response = JSON.parse(xhr.responseText) |
| | | if (response && response.success) { |
| | | console.log(response.data.result) |
| | | debugger |
| | | this.setHeatmapData(response.data.result) |
| | | 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.mockAsync |
| | | }.bind(this) |
| | | this.querying = false |
| | | }).catch(() => { |
| | | this.querying = false |
| | | }) |
| | | }, |
| | | formatPoint(data) { |
| | | var converters = { |
| | | "ba8c1624-55a7-4f20-9c54-01e56448aeb5": { |
| | | "scale": 1, |
| | | "default": { |
| | | "scale": 0.66, |
| | | "offsetX": 0, |
| | | "offsetY": 0 |
| | | } |
| | | } |
| | | |
| | | var cv = converters[data.cameraId] |
| | | 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: ((topLeft.y + bottomRight.y) * cv.scale + cv.offsetX * 2) / 2, |
| | | // value: data.stayTime |
| | | value: 0 |
| | | y: ((bottomRight.y) * cv.scale + cv.offsetY), |
| | | value: data.stayTime |
| | | }; |
| | | if (dataPoint.y > 720) { |
| | | dataPoint.y = 720 |
| | | } |
| | | |
| | | return dataPoint |
| | | } |
| | |
| | | background-image: linear-gradient(-180deg, #ffffff 13%, #e9ebf2 100%); |
| | | } |
| | | .toolbar { |
| | | width: 680px; |
| | | width: 850px; |
| | | height: 60px; |
| | | //background: rgba(0,0,0,.3); |
| | | position: absolute; |
| | |
| | | .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: .5; |
| | | opacity: 0.5; |
| | | border-radius: 50%; |
| | | position: absolute; |
| | | z-index: 1000; |