ZZJ
2021-11-09 ccee429d379e0108b7445f72ade8d97c110a6fb3
src/pages/heatCamera/index/App.vue
@@ -2,134 +2,256 @@
  <div class="heatCamera">
    <div class="camera">
      <nav class="header-nav">
          <div class="toolbar">
            <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="small"></el-date-picker>
              <el-button type="primary" size="small">查询</el-button>
          </div>
        <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">
        <!-- <el-image src="/timg.jpg" fit="contain" ref="img"></el-image> -->
        <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>
import Heatmap from 'heatmap.js';
import {getHeatCameraData} from '@/api/heatCamera'
import { getHeatCameraData } from '@/api/heatCamera'
import { getCamerasByServer } from '@/api/pollConfig'
import { getPersonData } from './api'
export default {
  data(){
    return {
      publicPath: process.env.BASE_URL,
      timeRange: [new Date(2020, 8, 20, 8), new Date(2020, 9, 20, 8)],
      params: {
        cameraIds: ["c6fd8f31-248f-49fc-93e0-dedac889197b","c41a2f34-bd2e-41af-9bc0-51e6dcd03523"],
        startTime: '',
        endTime: '',
  name: "heatCamera",
  computed: {
    baseImg() {
      let imgUrl = "";
      if (this.camera.snapshot_url && this.camera.snapshot_url.length) {
        imgUrl = '/httpImage/' + this.camera.snapshot_url
      }
      return imgUrl
    }
  },
  mounted(){
    console.log(Heatmap.create)
    setTimeout(()=>{
      this.mockAsync()
    },2000);
  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,
    }
  },
  methods:{
    timeChange(val){
      console.log(val);
      this.params.startTime = val[0];
      this.params.endTime = val[1];
      this.renderHeatMap(this.params)
    },
    mockAsync(){
      var config = {
        container: document.querySelector('.img-area'),
        radius: 10,
        maxOpacity: .75,
        minOpacity: 0,
        blur: .75,
        gradient: {
          '.5': 'blue',
          '.8': 'red',
          '0.95': 'white',
          '0.6': 'yellow',
          '0.5': 'green'
  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 data = {
        max: 700,
      var points = {
        max: 300,
        min: 0,
        data: []
      }
      for (var i = 10; i < 700; i++) {
        var dataPoint = {
          x: Math.floor(Math.random() * i),
          y: Math.floor(Math.random() * i),
          value: Math.floor(Math.random() * i)
        };
        var dataCenter = {
          x: i,
          y: i,
          value: 30 + i
        }
        data.data.push(dataPoint, dataCenter)
      if (this.heatmapInstance === null) {
        this.heatmapInstance = Heatmap.create(heatmapConfig);
      } else {
        this.heatmapInstance.setData(points);
      }
      //var heatmapInstance = h337.create(config);
      var heatmapInstance = Heatmap.create(config);
      heatmapInstance.setData(data);
      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);
      }
    },
    renderHeatMap(params){
      getHeatCameraData(params).then(res=>{
        debugger
    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: 500px;
      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;
      }
      .el-button{
        vertical-align: middle;
        margin-left: 4px;
      }
    }
    .img-area{
      margin: 30px auto;
      width: 1200px;
      //position: relative;
      font-size: 0;
    }
    img{
      display: block;
    }
.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>