4 changed files with 437 additions and 7 deletions
			
			
		@ -0,0 +1,430 @@ | 
				
			|||
<!--    | 
				
			|||
  *@描述: 云台控制 | 
				
			|||
  *@作者:  | 
				
			|||
  *@日期:  | 
				
			|||
  *@版本:1.0 | 
				
			|||
  */ | 
				
			|||
  --> | 
				
			|||
<template> | 
				
			|||
  <div> | 
				
			|||
    <div class="camera-control"> | 
				
			|||
      <div class="camera-operate"> | 
				
			|||
        <div class="camera-direct"> | 
				
			|||
         | 
				
			|||
          <!--上--> | 
				
			|||
          <div class="upButton" style="background-position:-30px 0" @mousedown="upStart()" @mouseup="stopMove()"> | 
				
			|||
          </div> | 
				
			|||
        | 
				
			|||
          <!--左--> | 
				
			|||
          <div class="leftButton" style="background-position:0 -30px" @mousedown="leftStart()" @mouseup="stopMove()"> | 
				
			|||
          </div> | 
				
			|||
         | 
				
			|||
          <!--右--> | 
				
			|||
          <div class="rightButton" style="background-position:-60px -30px" @mousedown="rightStart()" | 
				
			|||
            @mouseup="stopMove()"> | 
				
			|||
          </div> | 
				
			|||
 | 
				
			|||
          <!--下--> | 
				
			|||
          <div class="downButton" style="background-position:-30px -60px" @mousedown="downStart()" | 
				
			|||
            @mouseup="stopMove()"> | 
				
			|||
          </div> | 
				
			|||
       | 
				
			|||
        </div> | 
				
			|||
        <!-- <div class="camera-function"> | 
				
			|||
          <div class="function-box"> | 
				
			|||
            <div class="function-item" | 
				
			|||
              style="background-position:-128px 0;border-right: 1px rgba(179, 177, 177, 0.97) dotted;" | 
				
			|||
              @mousedown="zoomIn()" @mouseup="stopMove()" title="变倍+"> | 
				
			|||
            </div> | 
				
			|||
            <div class="function-item" style="background-position:-92px 0;" @mousedown="zoomOut()" @mouseup="stopMove()" | 
				
			|||
              title="变倍-"> | 
				
			|||
            </div> | 
				
			|||
          </div> --> | 
				
			|||
          <!-- <div class="function-box"> | 
				
			|||
            <div class="function-item" | 
				
			|||
              style="background-position:-128px -30px;border-right:1px rgba(179, 177, 177, 0.97) dotted; " | 
				
			|||
              @mousedown="focusIn()" @mouseup="focusStop()" title="变焦+"> | 
				
			|||
            </div> | 
				
			|||
            <div class="function-item" style="background-position:-92px -30px;" @mousedown="focusOut()" | 
				
			|||
              @mouseup="focusStop()" title="变焦-"> | 
				
			|||
            </div> | 
				
			|||
          </div> --> | 
				
			|||
          <!-- <div class="function-box"> | 
				
			|||
            <div class="function-item" | 
				
			|||
              style="background-position:-202px 0; border-right:1px rgba(179, 177, 177, 0.97) dotted;" | 
				
			|||
              @mousedown="handleScreenSnap()" title="抓拍"> | 
				
			|||
            </div> | 
				
			|||
            <div class="function-item" style="background-position:-162px -89px;" @mousedown="openImgListDialog()" | 
				
			|||
              title="抓拍列表"> | 
				
			|||
            </div> | 
				
			|||
          </div> --> | 
				
			|||
        </div> | 
				
			|||
      </div> | 
				
			|||
    </div> | 
				
			|||
    | 
				
			|||
  </div> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script lang="ts" setup> | 
				
			|||
import { axios } from '@/utils/axios'; | 
				
			|||
import Qs from 'qs' | 
				
			|||
import { apiUrl } from "@/axios"; | 
				
			|||
import { onBeforeUnmount, onMounted, ref } from 'vue'; | 
				
			|||
 | 
				
			|||
const ip = ref('337342439297349') | 
				
			|||
const onvifUrl = ref(apiUrl.OnvifApiUrl) | 
				
			|||
const currentStep = ref(5); | 
				
			|||
const autoFlag = ref(false) | 
				
			|||
const screenSnapList: any = ref({ | 
				
			|||
  title: '抓拍列表', | 
				
			|||
  visible: false | 
				
			|||
}) | 
				
			|||
const url: any = ref({ | 
				
			|||
  isExist: '/onvif/isExists', | 
				
			|||
  add: '/onvif/register', | 
				
			|||
  ptzMove: '/onvif/continuousMove', | 
				
			|||
  ptzStopMove: '/onvif/stopMove', | 
				
			|||
  focusMove: '/onvif/focusContinuousMove', | 
				
			|||
  focusStopMove: '/onvif/focusStopMove', | 
				
			|||
  getSnapshot: '/onvif/getSnapshotUrl', | 
				
			|||
  // screenSnap: 'camera/setting/screenSnap', | 
				
			|||
  delete: '/onvif/delete' | 
				
			|||
}) | 
				
			|||
 | 
				
			|||
onMounted(() => { | 
				
			|||
  checkExistOnvif(); | 
				
			|||
}) | 
				
			|||
onBeforeUnmount(() => { | 
				
			|||
  //注销 | 
				
			|||
  onvifOperateHandler(url.value.delete, 'post', { cameraId: ip.value }) | 
				
			|||
}) | 
				
			|||
 | 
				
			|||
 | 
				
			|||
//发送指令 | 
				
			|||
function onvifOperateHandler(url: any, method: any, params: any, callback: any = {}) { | 
				
			|||
  url = onvifUrl.value + url | 
				
			|||
  let reqParams = { url: url, method: method } | 
				
			|||
  let dataParam = (method === 'get') ? { params: params } : { data: Qs.stringify(params) } | 
				
			|||
  Object.assign(reqParams, dataParam); | 
				
			|||
  // console.log("reqParams",reqParams); | 
				
			|||
  axios(reqParams).then((res: any) => { | 
				
			|||
    // console.log(res); | 
				
			|||
    if (res.status == 200) { | 
				
			|||
      if (!res.Errors) { | 
				
			|||
        // console.log("成功"); | 
				
			|||
        if (callback && typeof callback === 'function') { | 
				
			|||
          callback(res) | 
				
			|||
        } | 
				
			|||
      } else { | 
				
			|||
        // callUtil.$emit('openNotification', res.Errors, 2, 'warning', '50px') | 
				
			|||
      } | 
				
			|||
    } else { | 
				
			|||
      // callUtil.$emit('openNotification', '云台控制异常', 2, 'error', '50px') | 
				
			|||
    } | 
				
			|||
  }) | 
				
			|||
} | 
				
			|||
 | 
				
			|||
 | 
				
			|||
//检查是否已经注册 | 
				
			|||
function checkExistOnvif() { | 
				
			|||
  // Check onvif server is exists, if not exists , add it | 
				
			|||
  let params = { cameraId: ip.value } | 
				
			|||
  onvifOperateHandler(url.value.isExist, 'get', params, (res: any) => { | 
				
			|||
    console.log(res); | 
				
			|||
    if (!res.isSuccess || res.data !== true) { | 
				
			|||
      console.log("不存在,请先注册"); | 
				
			|||
      onvifOperateHandler(url.value.add, 'post', params, (res: any) => { | 
				
			|||
        console.log("注册信息", res); | 
				
			|||
        console.log("注册成功"); | 
				
			|||
      }) | 
				
			|||
    } | 
				
			|||
  }) | 
				
			|||
} | 
				
			|||
 | 
				
			|||
//指令类型 | 
				
			|||
function createPtzParam(instruct: any, step: any) { | 
				
			|||
  let ptzParam | 
				
			|||
  let speed = 0.1 * step | 
				
			|||
  switch (instruct) { | 
				
			|||
    case 'up': | 
				
			|||
      ptzParam = new Float32Array([0, 1, 0]) | 
				
			|||
      break | 
				
			|||
    case 'leftUp': | 
				
			|||
      ptzParam = new Float32Array([-1, 1, 0]) | 
				
			|||
      break | 
				
			|||
    case 'rightUp': | 
				
			|||
      ptzParam = new Float32Array([1, 1, 0]) | 
				
			|||
      break | 
				
			|||
    case 'down': | 
				
			|||
      ptzParam = new Float32Array([0, -1, 0]) | 
				
			|||
      break | 
				
			|||
    case 'leftDown': | 
				
			|||
      ptzParam = new Float32Array([-1, -1, 0]) | 
				
			|||
      break | 
				
			|||
    case 'rightDown': | 
				
			|||
      ptzParam = new Float32Array([1, -1, 0]) | 
				
			|||
      break | 
				
			|||
    case 'left': | 
				
			|||
      ptzParam = new Float32Array([-1, 0, 0]) | 
				
			|||
      break | 
				
			|||
    case 'right': | 
				
			|||
      ptzParam = new Float32Array([1, 0, 0]) | 
				
			|||
      break | 
				
			|||
    case 'zoomIn': | 
				
			|||
      ptzParam = new Float32Array([0, 0, 1]) | 
				
			|||
      break | 
				
			|||
    case 'zoomOut': | 
				
			|||
      ptzParam = new Float32Array([0, 0, -1]) | 
				
			|||
      break | 
				
			|||
    default: | 
				
			|||
      ptzParam = new Float32Array([0, 0, 0]) | 
				
			|||
  } | 
				
			|||
  return { pan: ptzParam[0] * speed, tilt: ptzParam[1] * speed, zoom: ptzParam[2] * speed } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
//停止移动 | 
				
			|||
function stopMove() { | 
				
			|||
  let params = { cameraId: ip.value } | 
				
			|||
  onvifOperateHandler(url.value.ptzStopMove, 'post', params) | 
				
			|||
} | 
				
			|||
 | 
				
			|||
//上 | 
				
			|||
function upStart() { | 
				
			|||
  let instruct = 'up' | 
				
			|||
  let step = currentStep.value | 
				
			|||
  let params = { cameraId: ip.value } | 
				
			|||
  let ptzParams = createPtzParam(instruct, step) | 
				
			|||
  Object.assign(params, ptzParams) | 
				
			|||
  onvifOperateHandler(url.value.ptzMove, 'post', params) | 
				
			|||
  // console.log("上", params); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
//下 | 
				
			|||
function downStart() { | 
				
			|||
  let instruct = 'down' | 
				
			|||
  let step = currentStep.value | 
				
			|||
  let params = { cameraId: ip.value } | 
				
			|||
  let ptzParams = createPtzParam(instruct, step) | 
				
			|||
  Object.assign(params, ptzParams) | 
				
			|||
  onvifOperateHandler(url.value.ptzMove, 'post', params) | 
				
			|||
  console.log("下", params); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
//左 | 
				
			|||
function leftStart() { | 
				
			|||
  let instruct = 'left' | 
				
			|||
  let step = currentStep.value | 
				
			|||
  let params = { cameraId: ip.value } | 
				
			|||
  let ptzParams = createPtzParam(instruct, step) | 
				
			|||
  Object.assign(params, ptzParams) | 
				
			|||
  onvifOperateHandler(url.value.ptzMove, 'post', params) | 
				
			|||
} | 
				
			|||
//右 | 
				
			|||
function rightStart() { | 
				
			|||
  let instruct = 'right' | 
				
			|||
  let step = currentStep.value | 
				
			|||
  let params = { cameraId: ip.value } | 
				
			|||
  let ptzParams = createPtzParam(instruct, step) | 
				
			|||
  Object.assign(params, ptzParams) | 
				
			|||
  onvifOperateHandler(url.value.ptzMove, 'post', params) | 
				
			|||
} | 
				
			|||
 | 
				
			|||
//变倍+ | 
				
			|||
function zoomIn() { | 
				
			|||
  let instruct = 'zoomIn' | 
				
			|||
  let step = currentStep.value | 
				
			|||
  let params = { cameraId: ip.value } | 
				
			|||
  let ptzParams = createPtzParam(instruct, step) | 
				
			|||
  Object.assign(params, ptzParams) | 
				
			|||
  onvifOperateHandler(url.value.ptzMove, 'post', params) | 
				
			|||
} | 
				
			|||
//变倍- | 
				
			|||
function zoomOut() { | 
				
			|||
  let instruct = 'zoomOut' | 
				
			|||
  let step = currentStep.value | 
				
			|||
  let params = { cameraId: ip.value } | 
				
			|||
  let ptzParams = createPtzParam(instruct, step) | 
				
			|||
  Object.assign(params, ptzParams) | 
				
			|||
  onvifOperateHandler(url.value.ptzMove, 'post', params) | 
				
			|||
} | 
				
			|||
 | 
				
			|||
//变焦+ | 
				
			|||
function focusIn() { | 
				
			|||
  let step = currentStep.value | 
				
			|||
  let params = { cameraId: ip.value } | 
				
			|||
  Object.assign(params, { speed: (0.1 * step) }) | 
				
			|||
  onvifOperateHandler(url.value.focusMove, 'post', params) | 
				
			|||
} | 
				
			|||
//变焦- | 
				
			|||
function focusOut() { | 
				
			|||
  let step = currentStep.value | 
				
			|||
  let params = { cameraId: ip.value } | 
				
			|||
  Object.assign(params, { speed: (-0.1 * step) }) | 
				
			|||
  onvifOperateHandler(url.value.focusMove, 'post', params) | 
				
			|||
} | 
				
			|||
//停止变焦 | 
				
			|||
function focusStop() { | 
				
			|||
  onvifOperateHandler(url.value.focusStopMove, 'post', { cameraId: ip.value }) | 
				
			|||
} | 
				
			|||
 | 
				
			|||
//抓拍 | 
				
			|||
function handleScreenSnap(){ | 
				
			|||
 | 
				
			|||
} | 
				
			|||
function openImgListDialog(){ | 
				
			|||
 | 
				
			|||
 | 
				
			|||
} | 
				
			|||
 | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<style scoped lang="less"> | 
				
			|||
.camera-control { | 
				
			|||
  /* color: #080000; */ | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.camera-control .camera-operate { | 
				
			|||
  display: -webkit-flex; | 
				
			|||
  /* Safari */ | 
				
			|||
  display: flex; | 
				
			|||
  flex-direction: row; | 
				
			|||
  justify-content: center; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
.camera-control .camera-direct { | 
				
			|||
  display: -webkit-flex; | 
				
			|||
  /* Safari */ | 
				
			|||
  width: 110px; | 
				
			|||
  height: 100px; | 
				
			|||
  display: flex; | 
				
			|||
  flex-direction: row; | 
				
			|||
  flex-wrap: wrap; | 
				
			|||
  padding: 10px 10px 0 0; | 
				
			|||
  /*margin: auto;*/ | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.camera-control .camera-direct .direct-item { | 
				
			|||
  width: 30px; | 
				
			|||
  height: 30px; | 
				
			|||
  background-repeat: no-repeat; | 
				
			|||
  background-size: 400px 300px; | 
				
			|||
  background-image: url('@/assets/images/ptzIcons/ptz-icons.png'); | 
				
			|||
  margin: 1px 1px 1px 1px; | 
				
			|||
  border: 1px rgba(190, 188, 188, 0.97) solid; | 
				
			|||
  border-radius: 1px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.camera-control .camera-direct .direct-item:hover { | 
				
			|||
  background-color: rgba(208, 212, 208, 0.3); | 
				
			|||
  background-image: url('@/assets/images/ptzIcons/ptz-icons-on.png'); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.camera-control .camera-direct .direct-item .img { | 
				
			|||
  width: 100%; | 
				
			|||
  height: 100%; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.camera-control .camera-function { | 
				
			|||
  display: -webkit-flex; | 
				
			|||
  /* Safari */ | 
				
			|||
  /*margin-left: 20px;*/ | 
				
			|||
  margin-left: 10px; | 
				
			|||
  width: 90px; | 
				
			|||
  height: 120px; | 
				
			|||
  display: flex; | 
				
			|||
  flex-direction: column; | 
				
			|||
  flex-wrap: wrap; | 
				
			|||
  padding: 10px 0 0 10px; | 
				
			|||
  /*margin: auto;*/ | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.camera-control .camera-function .function-box { | 
				
			|||
  display: -webkit-flex; | 
				
			|||
  /* Safari */ | 
				
			|||
  height: 30px; | 
				
			|||
  width: 65px; | 
				
			|||
  display: flex; | 
				
			|||
  flex-direction: row; | 
				
			|||
  border: 1px rgba(190, 188, 188, 0.97) solid; | 
				
			|||
  border-radius: 1px; | 
				
			|||
  margin: 1px 1px 1px 1px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.camera-control .camera-function .function-item { | 
				
			|||
  width: 32px; | 
				
			|||
  height: 29px; | 
				
			|||
  background-repeat: no-repeat; | 
				
			|||
  background-size: 400px 300px; | 
				
			|||
 | 
				
			|||
  background-image: url('@/assets/images/ptzIcons/ptz-icons.png'); | 
				
			|||
  /*border: 1px rgba(179, 177, 177, 0.64) solid;*/ | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.camera-control .camera-function .function-item:hover { | 
				
			|||
  background-color: rgba(208, 212, 208, 0.3); | 
				
			|||
  background-image: url('@/assets/images/ptzIcons/ptz-icons-on.png'); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.camera-control .camera-function .function-item .img { | 
				
			|||
  width: 100%; | 
				
			|||
  height: 100%; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
/* 滑动输入条 */ | 
				
			|||
input[type='range'] { | 
				
			|||
  display: block; | 
				
			|||
  -webkit-appearance: none; | 
				
			|||
  background-color: #bdc3c7; | 
				
			|||
  width: 100%; | 
				
			|||
  height: 5px; | 
				
			|||
  margin: 6% auto; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
input[type='range']::-webkit-slider-thumb { | 
				
			|||
  -webkit-appearance: none; | 
				
			|||
  height: 20px; | 
				
			|||
  width: 20px; | 
				
			|||
  margin-top: -5px; | 
				
			|||
  /*使滑块超出轨道部分的偏移量相等*/ | 
				
			|||
  background: #ffffff; | 
				
			|||
  border-radius: 50%; | 
				
			|||
  /*外观设置为圆形*/ | 
				
			|||
  border: solid 0.125em rgba(205, 224, 230, 0.5); | 
				
			|||
  /*设置边框*/ | 
				
			|||
  box-shadow: 0 0.125em 0.125em #3b4547; | 
				
			|||
  /*添加底部阴影*/ | 
				
			|||
  cursor: pointer; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
input[type='range']::-webkit-slider-runnable-track { | 
				
			|||
  height: 10px; | 
				
			|||
  border-radius: 10px; | 
				
			|||
  /*将轨道设为圆角的*/ | 
				
			|||
  box-shadow: 0 1px 1px #def3f8, inset 0 0.125em 0.125em #0d1112; | 
				
			|||
  /*轨道内置阴影效果*/ | 
				
			|||
} | 
				
			|||
 | 
				
			|||
input[type='range']:focus { | 
				
			|||
  outline: none; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
input[type='range']::-webkit-slider-thumb:hover { | 
				
			|||
  border: 5px solid #b00303; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
input[type='range']::-webkit-slider-thumb:active { | 
				
			|||
  transform: scale(1.2); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
 | 
				
			|||
.upButton{ | 
				
			|||
  width: 100%; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
 | 
				
			|||
</style> | 
				
			|||
					Loading…
					
					
				
		Reference in new issue