|
|
@@ -0,0 +1,394 @@
|
|
|
+<template>
|
|
|
+ <div style="display: flex; justify-content: left;">
|
|
|
+ <div class="control-wrapper">
|
|
|
+ <div class="control-btn control-top" @mousedown="ptzCamera('up')" @mouseup="ptzCamera('stop')">
|
|
|
+ <i class="el-icon-caret-top"></i>
|
|
|
+ <div class="control-inner-btn control-inner"></div>
|
|
|
+ </div>
|
|
|
+ <div class="control-btn control-left" @mousedown="ptzCamera('left')" @mouseup="ptzCamera('stop')">
|
|
|
+ <i class="el-icon-caret-left"></i>
|
|
|
+ <div class="control-inner-btn control-inner"></div>
|
|
|
+ </div>
|
|
|
+ <div class="control-btn control-bottom" @mousedown="ptzCamera('down')" @mouseup="ptzCamera('stop')">
|
|
|
+ <i class="el-icon-caret-bottom"></i>
|
|
|
+ <div class="control-inner-btn control-inner"></div>
|
|
|
+ </div>
|
|
|
+ <div class="control-btn control-right" @mousedown="ptzCamera('right')" @mouseup="ptzCamera('stop')">
|
|
|
+ <i class="el-icon-caret-right"></i>
|
|
|
+ <div class="control-inner-btn control-inner"></div>
|
|
|
+ </div>
|
|
|
+ <div class="control-round">
|
|
|
+ <div class="control-round-inner"><i class="fa fa-pause-circle"></i></div>
|
|
|
+ </div>
|
|
|
+ <!-- 放大 -->
|
|
|
+ <div style="position: absolute; left: 7.25rem; top: -1.1rem" @mousedown="ptzCamera('zoomin')" @mouseup="ptzCamera('stop')"><i class="el-icon-zoom-in control-zoom-btn" style="font-size: 1.875rem;"></i></div>
|
|
|
+ <!-- 聚焦 -->
|
|
|
+
|
|
|
+ <div style="position: absolute; left: 7.25rem; top: 1.25rem"
|
|
|
+ @click="ptzCameraFocus('focus')" >
|
|
|
+ <i class="el-icon-aim control-zoom-btn" style="font-size: 1.875rem;"></i>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 缩小 -->
|
|
|
+ <div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;" @mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')"><i class="el-icon-zoom-out control-zoom-btn"></i></div>
|
|
|
+ <div class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 9rem;">
|
|
|
+ <el-slider v-model="controSpeed" :max="255"></el-slider>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="control-panel">
|
|
|
+ <el-button-group>
|
|
|
+ <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center" size="medium">预置位编号</el-tag>
|
|
|
+ <el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini" v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1" :max="255"></el-input-number>
|
|
|
+ <el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="presetPosition(129, presetPos)">设置</el-button>
|
|
|
+ <el-button style="position: absolute; left: 27rem; top: 0rem; width: 5rem" size="mini" type="primary" icon="el-icon-place" @click="presetPosition(130, presetPos)">调用</el-button>
|
|
|
+ <el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">删除</el-button>
|
|
|
+ <el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">巡航速度</el-tag>
|
|
|
+ <el-input-number style="position: absolute; left: 5rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number>
|
|
|
+ <el-button style="position: absolute; left: 11rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(134, cruisingGroup, cruisingSpeed)">设置</el-button>
|
|
|
+ <el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">停留时间</el-tag>
|
|
|
+ <el-input-number style="position: absolute; left: 21rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingTime" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number>
|
|
|
+ <el-button style="position: absolute; left: 27rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-timer" @click="setSpeedOrTime(135, cruisingGroup, cruisingTime)">设置</el-button>
|
|
|
+ <el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center" size="medium">巡航组编号</el-tag>
|
|
|
+ <el-input-number style="position: absolute; left: 5rem; top: 4.5rem; width: 6rem" size="mini" v-model="cruisingGroup" controls-position="right" :precision="0" :min="0" :max="255"></el-input-number>
|
|
|
+ <el-button style="position: absolute; left: 11rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="setCommand(132, cruisingGroup, presetPos)">添加点</el-button>
|
|
|
+ <el-button style="position: absolute; left: 16rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="setCommand(133, cruisingGroup, presetPos)">删除点</el-button>
|
|
|
+ <el-button style="position: absolute; left: 21rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete" @click="setCommand(133, cruisingGroup, 0)">删除组</el-button>
|
|
|
+ <el-button style="position: absolute; left: 27rem; top: 5rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(136, cruisingGroup, 0)">巡航</el-button>
|
|
|
+ <el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center" size="medium">扫描速度</el-tag>
|
|
|
+ <el-input-number style="position: absolute; left: 5rem; top: 7rem; width: 6rem" size="mini" v-model="scanSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number>
|
|
|
+ <el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">设置</el-button>
|
|
|
+ <el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center" size="medium">扫描组编号</el-tag>
|
|
|
+ <el-input-number style="position: absolute; left: 5rem; top: 9rem; width: 6rem" size="mini" v-model="scanGroup" controls-position="right" :precision="0" :step="1" :min="0" :max="255"></el-input-number>
|
|
|
+ <el-button style="position: absolute; left: 11rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-left" @click="setCommand(137, scanGroup, 1)">左边界</el-button>
|
|
|
+ <el-button style="position: absolute; left: 16rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-right" @click="setCommand(137, scanGroup, 2)">右边界</el-button>
|
|
|
+ <el-button style="position: absolute; left: 27rem; top: 7rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(137, scanGroup, 0)">扫描</el-button>
|
|
|
+ <el-button style="position: absolute; left: 27rem; top: 9rem; width: 5rem" size="mini" type="danger" icon="el-icon-switch-button" @click="ptzCamera('stop')">停止</el-button>
|
|
|
+ </el-button-group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import handle from "@/until/handle";
|
|
|
+
|
|
|
+let queryTimer = null;
|
|
|
+let isZoom = null;
|
|
|
+let sendStopTimer = null;
|
|
|
+let changToLongDownStateTimer = null;
|
|
|
+// 是否长按
|
|
|
+let isLongDown = null;
|
|
|
+export default {
|
|
|
+ name: "ptzControl",
|
|
|
+ props:{
|
|
|
+ deviceId:{require:true},
|
|
|
+ channelId:{require:true}
|
|
|
+ },
|
|
|
+ data(){
|
|
|
+ return {
|
|
|
+ isLoading: false,
|
|
|
+ tabActiveName: 'control',
|
|
|
+ controSpeed: 30,
|
|
|
+ zoomSpeed: 30,
|
|
|
+ presetPos: 1,
|
|
|
+ cruisingSpeed: 100,
|
|
|
+ cruisingTime: 5,
|
|
|
+ cruisingGroup: 0,
|
|
|
+ scanSpeed: 100,
|
|
|
+ scanGroup: 0,
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods:{
|
|
|
+ timeSendFocus(){
|
|
|
+ queryTimer = setTimeout(async ()=>{
|
|
|
+ await this.ptzCameraFocus();
|
|
|
+ queryTimer = null;
|
|
|
+ },700)
|
|
|
+ },
|
|
|
+ timeSendStop(){
|
|
|
+ console.log('短按自动跟发stop');
|
|
|
+ this.ptzCamera('stop');
|
|
|
+ },
|
|
|
+ async ptzCamera(command){
|
|
|
+ console.log('云台控制:' + command);
|
|
|
+ let isSendFocus = false;
|
|
|
+ let that = this;
|
|
|
+ let isAutoSendStop = false;
|
|
|
+ if(command === 'zoomin' || command === 'zoomout'){
|
|
|
+ isZoom = true;
|
|
|
+ if (queryTimer!=null){
|
|
|
+ // 中止
|
|
|
+ clearTimeout(queryTimer);
|
|
|
+ }
|
|
|
+ }else if(command === 'stop' && isZoom){
|
|
|
+ // 发送待定值
|
|
|
+ isSendFocus = true;
|
|
|
+ }else{
|
|
|
+
|
|
|
+ isZoom = false;
|
|
|
+ // down 发送特定指令值.
|
|
|
+ }
|
|
|
+ clearTimeout(sendStopTimer);
|
|
|
+ sendStopTimer = null;
|
|
|
+
|
|
|
+ // 不连续发送指令
|
|
|
+ if(command !== 'stop'){
|
|
|
+ isLongDown = false;
|
|
|
+ // 非停止指令
|
|
|
+ changToLongDownStateTimer = setTimeout(()=>{
|
|
|
+ isLongDown = true;
|
|
|
+ },1000)
|
|
|
+ }else{
|
|
|
+ // 确保不是自动对焦
|
|
|
+ if(!isLongDown && !isSendFocus){
|
|
|
+ // 短按阻止立即发送end,等待900ms发送end
|
|
|
+ sendStopTimer = setTimeout(()=>{
|
|
|
+ this.timeSendStop();
|
|
|
+ },1200);
|
|
|
+ console.log('进行短按操作');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 清除定时器
|
|
|
+ clearTimeout(changToLongDownStateTimer);
|
|
|
+ changToLongDownStateTimer = null;
|
|
|
+ }
|
|
|
+ let [err,res] = await handle(this.$axios({
|
|
|
+ method: 'post',
|
|
|
+ url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.zoomSpeed
|
|
|
+ }));
|
|
|
+ if(err){
|
|
|
+ console.error(err)}
|
|
|
+ if(isSendFocus){
|
|
|
+ this.timeSendFocus();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async ptzCameraFocus(){
|
|
|
+ // todo 发送聚焦http指令
|
|
|
+ console.log("摄像头聚焦");
|
|
|
+ let url = `/api/ptz/focus/`
|
|
|
+ url+=`${this.deviceId}/`;
|
|
|
+ url+=`${this.channelId}/`;
|
|
|
+ let [err,res] = await handle(this.$axios({
|
|
|
+ method: 'post',
|
|
|
+ url: url
|
|
|
+ }));
|
|
|
+ if(err){
|
|
|
+ console.error(err)}
|
|
|
+ },
|
|
|
+ presetPosition: function (cmdCode, presetPos) {
|
|
|
+ console.log('预置位控制:' + this.presetPos + ' : 0x' + cmdCode.toString(16));
|
|
|
+ let that = this;
|
|
|
+ this.$axios({
|
|
|
+ method: 'post',
|
|
|
+ url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '¶meter1=0¶meter2=' + presetPos + '&combindCode2=0'
|
|
|
+ }).then(function (res) {});
|
|
|
+ },
|
|
|
+ setSpeedOrTime: function (cmdCode, groupNum, parameter) {
|
|
|
+ let that = this;
|
|
|
+ let parameter2 = parameter % 256;
|
|
|
+ let combindCode2 = Math.floor(parameter / 256) * 16;
|
|
|
+ console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter2.toString(16) + ' 0x' + combindCode2.toString(16));
|
|
|
+ this.$axios({
|
|
|
+ method: 'post',
|
|
|
+ url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '¶meter1=' + groupNum + '¶meter2=' + parameter2 + '&combindCode2=' + combindCode2
|
|
|
+ }).then(function (res) {});
|
|
|
+ },
|
|
|
+ setCommand: function (cmdCode, groupNum, parameter) {
|
|
|
+ let that = this;
|
|
|
+ console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter.toString(16) + ' 0x0');
|
|
|
+ this.$axios({
|
|
|
+ method: 'post',
|
|
|
+ url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '¶meter1=' + groupNum + '¶meter2=' + parameter + '&combindCode2=0'
|
|
|
+ }).then(function (res) {});
|
|
|
+ },
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.control-wrapper {
|
|
|
+ position: relative;
|
|
|
+ width: 6.25rem;
|
|
|
+ height: 6.25rem;
|
|
|
+ max-width: 6.25rem;
|
|
|
+ max-height: 6.25rem;
|
|
|
+ border-radius: 100%;
|
|
|
+ margin-top: 1.5rem;
|
|
|
+ margin-left: 0.5rem;
|
|
|
+ float: left;
|
|
|
+}
|
|
|
+
|
|
|
+.control-panel {
|
|
|
+ position: relative;
|
|
|
+ top: 0;
|
|
|
+ left: 5rem;
|
|
|
+ height: 11rem;
|
|
|
+ max-height: 11rem;
|
|
|
+}
|
|
|
+
|
|
|
+.control-btn {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ position: absolute;
|
|
|
+ width: 44%;
|
|
|
+ height: 44%;
|
|
|
+ border-radius: 5px;
|
|
|
+ border: 1px solid #78aee4;
|
|
|
+ box-sizing: border-box;
|
|
|
+ transition: all 0.3s linear;
|
|
|
+}
|
|
|
+.control-btn:hover {
|
|
|
+ cursor:pointer
|
|
|
+}
|
|
|
+
|
|
|
+.control-btn i {
|
|
|
+ font-size: 20px;
|
|
|
+ color: #78aee4;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+.control-btn i:hover {
|
|
|
+ cursor:pointer
|
|
|
+}
|
|
|
+.control-zoom-btn:hover {
|
|
|
+ cursor:pointer
|
|
|
+}
|
|
|
+
|
|
|
+.control-round {
|
|
|
+ position: absolute;
|
|
|
+ top: 21%;
|
|
|
+ left: 21%;
|
|
|
+ width: 58%;
|
|
|
+ height: 58%;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.control-round-inner {
|
|
|
+ position: absolute;
|
|
|
+ left: 13%;
|
|
|
+ top: 13%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ width: 70%;
|
|
|
+ height: 70%;
|
|
|
+ font-size: 40px;
|
|
|
+ color: #78aee4;
|
|
|
+ border: 1px solid #78aee4;
|
|
|
+ border-radius: 100%;
|
|
|
+ transition: all 0.3s linear;
|
|
|
+}
|
|
|
+
|
|
|
+.control-inner-btn {
|
|
|
+ position: absolute;
|
|
|
+ width: 60%;
|
|
|
+ height: 60%;
|
|
|
+ background: #fafafa;
|
|
|
+}
|
|
|
+
|
|
|
+.control-top {
|
|
|
+ top: -8%;
|
|
|
+ left: 27%;
|
|
|
+ transform: rotate(-45deg);
|
|
|
+ border-radius: 5px 100% 5px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.control-top i {
|
|
|
+ transform: rotate(45deg);
|
|
|
+ border-radius: 5px 100% 5px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.control-top .control-inner {
|
|
|
+ left: -1px;
|
|
|
+ bottom: 0;
|
|
|
+ border-top: 1px solid #78aee4;
|
|
|
+ border-right: 1px solid #78aee4;
|
|
|
+ border-radius: 0 100% 0 0;
|
|
|
+}
|
|
|
+
|
|
|
+.control-top .fa {
|
|
|
+ transform: rotate(45deg) translateY(-7px);
|
|
|
+}
|
|
|
+
|
|
|
+.control-left {
|
|
|
+ top: 27%;
|
|
|
+ left: -8%;
|
|
|
+ transform: rotate(45deg);
|
|
|
+ border-radius: 5px 0 5px 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.control-left i {
|
|
|
+ transform: rotate(-45deg);
|
|
|
+}
|
|
|
+
|
|
|
+.control-left .control-inner {
|
|
|
+ right: -1px;
|
|
|
+ top: -1px;
|
|
|
+ border-bottom: 1px solid #78aee4;
|
|
|
+ border-left: 1px solid #78aee4;
|
|
|
+ border-radius: 0 0 0 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.control-left .fa {
|
|
|
+ transform: rotate(-45deg) translateX(-7px);
|
|
|
+}
|
|
|
+
|
|
|
+.control-right {
|
|
|
+ top: 27%;
|
|
|
+ right: -8%;
|
|
|
+ transform: rotate(45deg);
|
|
|
+ border-radius: 5px 100% 5px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.control-right i {
|
|
|
+ transform: rotate(-45deg);
|
|
|
+}
|
|
|
+
|
|
|
+.control-right .control-inner {
|
|
|
+ left: -1px;
|
|
|
+ bottom: -1px;
|
|
|
+ border-top: 1px solid #78aee4;
|
|
|
+ border-right: 1px solid #78aee4;
|
|
|
+ border-radius: 0 100% 0 0;
|
|
|
+}
|
|
|
+
|
|
|
+.control-right .fa {
|
|
|
+ transform: rotate(-45deg) translateX(7px);
|
|
|
+}
|
|
|
+
|
|
|
+.control-bottom {
|
|
|
+ left: 27%;
|
|
|
+ bottom: -8%;
|
|
|
+ transform: rotate(45deg);
|
|
|
+ border-radius: 0 5px 100% 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.control-bottom i {
|
|
|
+ transform: rotate(-45deg);
|
|
|
+}
|
|
|
+
|
|
|
+.control-bottom .control-inner {
|
|
|
+ top: -1px;
|
|
|
+ left: -1px;
|
|
|
+ border-bottom: 1px solid #78aee4;
|
|
|
+ border-right: 1px solid #78aee4;
|
|
|
+ border-radius: 0 0 100% 0;
|
|
|
+}
|
|
|
+
|
|
|
+.control-bottom .fa {
|
|
|
+ transform: rotate(-45deg) translateY(7px);
|
|
|
+}
|
|
|
+.trank {
|
|
|
+ width: 80%;
|
|
|
+ height: 180px;
|
|
|
+ text-align: left;
|
|
|
+ padding: 0 10%;
|
|
|
+ overflow: auto;
|
|
|
+}
|
|
|
+.trankInfo {
|
|
|
+ width: 80%;
|
|
|
+ padding: 0 10%;
|
|
|
+}
|
|
|
+</style>
|