VUE 轮盘方向控制获取角度

 

功能实现样式 

 

(拖拽中间的球  获取当前的角度)

 

百分比样式 适配多种组件

<template>
   <div class="videoControl"  @mousemove="movePoint">  

        <!-- <div class="cubeList" >
            <p></p>
            <p></p> 
        </div>  -->



        <div class="round"> 
            
            <div class="video videoData">
                

                <div class="movePoint" :class="downStatus?'pos':''" :style="{'left': left + 'px', 'top': top + 'px'}" @mousedown="downPoint"  @mouseup="upPoint">
                    
                </div>

            </div>
        </div>

        <ul>
            <li @mousedown="toMove(8)"  @mouseup="upPoint"><img src="@/assets/img/icon/fangda.svg" alt=""></li>
            <li @mousedown="toMove(9)"  @mouseup="upPoint"><img src="@/assets/img/icon/suoxiao.svg" alt=""></li>
            <li><img src="@/assets/img/icon/xiangji1.svg" alt=""></li>
            <li @click="presetMove"><img src="@/assets/img/icon/zhongzhi.svg" alt=""></li>
        </ul>         

    </div> 


</template>

<script lang="ts">
import { Options, Vue} from 'vue-class-component';
import axios from "axios";
import { message} from 'ant-design-vue';

const http = axios.create({
    baseURL: 'https://open.ys7.com/api/lapp/device/', 
    timeout: 20000, // request timeout
});

http.interceptors.request.use(
    config => {
            let headers:any = config.headers;
            headers['Content-Type'] = 'application/x-www-form-urlencoded';            
        return config;
    }
)

http.interceptors.response.use(
    response => {
        let data = response.data;
        if(data.code != 200) {

            message.error(data.msg)
        }
        return data;
    },
    error => {
        console.error(error);
    }
);


interface Point{
     x: number;
     y: number;   
}


let currentIndex:string|number = 1000000 //当前操作的方向


@Options({
  props: {
    msg: String,
    videoParams: null
  },

  watch: {
      downStatus:function (ne:any, old:any) {
          if(!ne) {
              this.upPoint()
          }
      }
  },  
  
  data: () => {
      return {
          a: 1,
          downStatus: false,
          left: 0,
          top: 0,
          offsetWidth: 0,
          pageX: 0,
          pageY: 0,
          moveWidth: 0, // 可移动区域长度
          status : false,
          status2: false,
      }
  },
  mounted() {
      let _this =this

      let video:any = document.querySelector('.videoData') 
 
      let crcile:any = document.querySelector('.movePoint')
      this.offsetWidth =  crcile.offsetWidth

      this.moveWidth =   video.offsetWidth / 1.5 - (crcile.offsetWidth / 1.5);
      
      window.addEventListener('mouseup', function(e:any) {
          _this.downStatus = false
      })
  },

    

  methods: {
      // 发送请求
      toRequstion() {
          
      },

      angle(start:Point,end:Point):number{
            let diff_x = end.x - start.x,
                diff_y = end.y - start.y;
            //返回角度,不是弧度
            return 360*Math.atan2(diff_y,diff_x)/(2*Math.PI);
     },


      upPoint(e:any) {
         let params = this.videoParams
         let data = `accessToken=${params.accessToken}&deviceSerial=${params.deviceSerial}&channelNo=${params.channelNo}`
          http.post('ptz/stop', data).then(res => {
              
          })
          currentIndex = 1000000  
          this.downStatus = false
      },

      downPoint(e:any) {
          this.left = e.offsetX  - (this.offsetWidth /2 )
          this.top = e.offsetY - (this.offsetWidth /2 )

          this.pageX = e.pageX
          this.pageY = e.pageY
          this.downStatus= true
      },

      // 获取方向
      getdirtion(value:number):number {
          let newValue = value
          if(value < 0) {
              newValue = 360 + value
          }  
          return newValue
      },

      // 请求方向接口
      getVideoDIrction(angle: number) {
          let part = 45;
          
          let fistAngle = 45/2
          let index = 0
 
          if(angle > fistAngle &&  angle <= (part + fistAngle) ) { // 右上方
            index = 6
          } else if(angle > (part + fistAngle)  &&  angle <= (2 * part + fistAngle)) { // 正上
            index = 0
          } else if(angle > (2 * part + fistAngle)  &&  angle <= (3 * part + fistAngle)) { // 左上
            index = 4
          } else if(angle > (3 * part + fistAngle)  &&  angle <= (4 * part + fistAngle)) { //
            index = 2
          } else if(angle > (4 * part + fistAngle)  &&  angle <= (5 * part + fistAngle)) { // 左下
            index = 5
          } else if(angle > (5 * part + fistAngle)  &&  angle <= (6 * part + fistAngle)) { //
            index = 1
          } else if(angle > (6 * part + fistAngle)  &&  angle <= (7 * part + fistAngle)) { // 右下
            index = 7
          } else { //
            index = 3
          }
          
          
          
          if(currentIndex != index) {
            this.toMove(index)
          }
            
        //   if(angle > 0)
      }, 
      
      // 移动视频
      toMove(index:number|string) {
          currentIndex = index
          let params = this.videoParams
            let data = `accessToken=${params.accessToken}&deviceSerial=${params.deviceSerial}&channelNo=${params.channelNo}&direction=${index}&speed=1`
            http.post('ptz/start', data).then(res => {
                console.log(res, 'start')
            })
      },
      
      // 调用预置点
      presetMove() {
          let params = this.videoParams
          let data = `accessToken=${params.accessToken}&deviceSerial=${params.deviceSerial}&channelNo=${params.channelNo}&index=1`;
          http.post('preset/move', data).then(res => {
             console.log(res, 'move')
          })
      },  


      
      movePoint(e:any) {
          if(this.downStatus) {
            let x =  e.pageX - this.pageX
            let y = e.pageY - this.pageY


            let pos = this.angle({x:0, y:0}, {x:x, y:-y})

            // 获取角度
            let angle =  this.getdirtion(pos)
            
            // 超过范围执行
            if(Math.abs(x) > this.moveWidth / 2 || Math.abs(y) >  this.moveWidth / 2 ) {
                this.getVideoDIrction(angle)
            }

   
            if(Math.abs(x) > this.moveWidth) {
                this.left = Math.cos( 2 * Math.PI / 360 * angle) * (this.moveWidth + this.offsetWidth/5)
                this.top =  Math.sin( 2 * Math.PI / 360 * angle) * (this.moveWidth + this.offsetWidth/5) * -1
                this.status = false    
            } else {
                this.status = true  
                if(this.status && this.status2) {
                    this.left = x
                } 
            }

            if(Math.abs(y) > this.moveWidth) {
                this.left = Math.cos( 2 * Math.PI / 360 * angle) * (this.moveWidth + this.offsetWidth/5)
                this.top =  Math.sin( 2 * Math.PI / 360 * angle) * (this.moveWidth + this.offsetWidth/5) * -1
                this.status2 = false 

            } else {
                this.status2 = true
                if(this.status && this.status2) {
                    this.top = y
                }

                
            }

   
          }
      }

  }
    
})
export default class HelloWorld extends Vue {
  msg!: string
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
      .videoControl {
        width: 100%;
        height: 100%;
        position: absolute;
        display: flex;
        justify-content: center;
        align-items: center;


        .cubeList {
            position: absolute;
            width: 100%;
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
            p:first-child {
            width: 100%;
            height: 10px;
            background-color: #122656;   
            }
            p:last-child {
                position: absolute;
                height: 100%;
                width: 10px;
                background-color: #122656;  
            }
        }

        ul {
            position: absolute;
            display: flex;
            justify-content: space-between;
            // align-content: flex-start;
            align-content: space-between;
            width: 100%;
            height: 100%;
            // top: 0;
            flex-wrap: wrap;
            li{
                width: 45%;
                height: 45%;
                
                display: flex;
                justify-content: center;
                position: relative;
                cursor: pointer; 
                user-select: none;
                background-image: url(../assets/img/icon/yueya.svg);
                background-repeat: no-repeat;
                background-size: 100% 100%;
                

                img {
                    width: 20%;
                    position: relative;
                    left: 12%;
                    top: -12%;
                }
            }

        li:active {
            background-image: url(../assets/img/icon/yueya2.svg);
        }

        li:nth-child(1) {
            img {
               transform: rotate(90deg); 
            }
            transform: rotate(-90deg);
        } 

        li:nth-child(3) {
            transform: rotate(-180deg);
            // top: 10px;
            img {
               transform: rotate(180deg); 
            }

        }
        li:nth-child(4) {
            transform: rotate(-270deg);
            // top: 10px;

        }        

            
        }
    
        

    } 

    .round {
        width: 50%;
        height: 50%;
    }


    .video {
        width: 100%;
        height: 100%;
        // background-color: rgba(12,27,61, 0.3);
        border-radius: 50%;
        display: flex;
        flex-wrap: wrap;
        position: relative;
        justify-content: center;
        align-items: center;
        z-index: 10;
        .movePoint {
            cursor: pointer;
            height: 50%;
            width: 50%;
            border: 2px solid #777B89;
            border-radius: 50%;
            cursor: pointer;
            background-color: #777B89;
        }
    }
    
    .pos {
        position: relative;

    }

    // .video>div {
    //     width: 50%;
    //     height: 50%;
    //     cursor: pointer;
    // }

    



</style>

 

posted @ 2022-03-31 17:16  大帅比2  阅读(454)  评论(0编辑  收藏  举报