JS實(shí)現(xiàn)簡單的操作桿旋轉(zhuǎn)示例詳解
一、實(shí)現(xiàn)效果
JS 簡單的操作桿旋轉(zhuǎn)實(shí)現(xiàn)
首先說明一下,請直接忽略背景圖,這里主要實(shí)現(xiàn)的是桿旋轉(zhuǎn)控制方向盤旋轉(zhuǎn)。
鼠標(biāo)移出控制區(qū)域,控制球復(fù)位
二、組成部分
創(chuàng)建 ballOption.js 文件,用以綁定控制球指定 dom,并初始化相關(guān)操作
創(chuàng)建 eleOption.js 文件,用以實(shí)現(xiàn)一些頻繁的 dom 操作
主要是通過鼠標(biāo)滑動事件控制“控制球”位置更改及獲取以屏幕上方向?yàn)?度的角度計(jì)算,來控制“方向盤”進(jìn)行旋轉(zhuǎn)。
目標(biāo)
1、監(jiān)聽鼠標(biāo)滑動的事件,并判斷 event 的 point 是否進(jìn)入到控制球,如果進(jìn)入,控制小球隨著鼠標(biāo)進(jìn)行移動。
2、鼠標(biāo)劃出控制區(qū)域,控制球復(fù)位,旋轉(zhuǎn)角度歸零。
3、判斷鼠標(biāo) point 點(diǎn)位置,通過反三角函數(shù)獲取角度。
4、暴露控制球與控制區(qū)域中心形成的旋轉(zhuǎn)角度,觸發(fā)外界事件(方向盤旋轉(zhuǎn))
三、代碼實(shí)現(xiàn)
1、操作控制
ballOption.js 文件
class BallOption{ //添加操作dom ID eleId //el操作對象 eleOption //控制球?qū)ο? ball //控制球尺寸 ballWidth ballHeight ballOffX ballOffY //是否觸碰過控制球 isTouchedBall = false //控制區(qū)域 optionRangeView optionRangeViewCenterPoint //上一次角度 lastDeg //角度回調(diào) angleCallBack //初始化操作 constructor(eleId,angleCallBack){ this.eleId = eleId this.angleCallBack = angleCallBack this.eleOption = new EleOption(eleId) } //創(chuàng)建操作框 createOptionView(){ if(this.eleId != undefined){ this.createOptionRangeView() this.createOptionBallView() } } //繪制操作范圍 createOptionRangeView(){ let width = this.eleOption.getEleWidth(this.eleOption.getCurrentEle()) let height = this.eleOption.getEleHeight(this.eleOption.getCurrentEle()) this.optionRangeView = this.eleOption.createEl('optionRangeViewEl') this.eleOption.addSubEl(this.eleOption.getCurrentEle(),this.optionRangeView) this.eleOption.setBackgroundColor(this.optionRangeView,'rgb(248,248,248)') this.eleOption.setWidth(this.optionRangeView,width) this.eleOption.setHeight(this.optionRangeView,height) this.eleOption.setCircle(this.optionRangeView) //添加拖拽事件 this.eleOption.addMoveEvent(optionRangeViewEl,this,this.makeBallFollowScroll,this.resetBall) } //控制球隨鼠標(biāo)滾 makeBallFollowScroll(point,ballOption){ let x = (point.x - ballOption.ballOffX) let y = (point.y - ballOption.ballOffY) let currentPoint = {x,y} if(ballOption.checkIsTouchControlBall(point)){ ballOption.eleOption.setCenter(ballOption.ball,currentPoint) ballOption.getCurrentAngle(point) } } //檢測是否碰觸過控制球 checkIsTouchControlBall(point){ if(!this.isTouchedBall){ let isTouchBall = ( point.x > this.optionRangeViewCenterPoint.x - this.ballWidth && point.x < this.optionRangeViewCenterPoint.x + this.ballWidth && point.y > this.optionRangeViewCenterPoint.y - this.ballHeight && point.y < this.optionRangeViewCenterPoint.y + this.ballHeight ) if(isTouchBall){ this.isTouchedBall = true this.eleOption.setTransparency(this.ball,100) } } return this.isTouchedBall } //鼠標(biāo)移出事件 resetBall(ballOption){ ballOption.isTouchedBall = false ballOption.eleOption.setCenter(ballOption.ball,ballOption.optionRangeViewCenterPoint) ballOption.eleOption.setTransparency(ballOption.ball,40) if(ballOption.angleCallBack){ ballOption.lastDeg = 0 ballOption.angleCallBack(ballOption.lastDeg) } } //計(jì)算角度 getCurrentAngle(point){ let addX = (point.x - this.eleOption.getEleWidth(this.optionRangeView) / 2.0) let addY = (point.y - this.eleOption.getEleHeight(this.optionRangeView) / 2.0) if(addY != 0){ let tan = addX / addY let angle = Math.atan(tan) this.lastDeg = (angle / Math.PI) * 180 if(addX <= 0 && addY < 0){ this.lastDeg = this.lastDeg } else if(addX <= 0 && addY > 0){ this.lastDeg = (180 - Math.abs(this.lastDeg)) } else if(addX >= 0 && addY > 0){ this.lastDeg = 180 + Math.abs(this.lastDeg) } else if(addX >= 0 && addY < 0){ this.lastDeg = (360 - Math.abs(this.lastDeg)) } } if(this.angleCallBack){ this.angleCallBack(360 - this.lastDeg) } } //繪制球滾動 createOptionBallView(){ let scale = 3.2 this.ballWidth = this.eleOption.getEleWidth(this.eleOption.getCurrentEle()) / scale this.ballHeight = this.eleOption.getEleHeight(this.eleOption.getCurrentEle()) / scale this.ballOffX = this.ballWidth / 2.0 this.ballOffY = this.ballHeight / 2.0 this.ball = this.eleOption.createEl('optionBallViewEl') this.eleOption.addSubEl(this.eleOption.getCurrentEle(),this.ball) this.eleOption.setBackgroundColor(this.ball,'black') this.eleOption.setWidth(this.ball,this.ballWidth) this.eleOption.setHeight(this.ball,this.ballHeight) this.eleOption.setCircle(this.ball) this.eleOption.setSupCenter(this.ball) this.eleOption.cancleUserInreface(this.ball) this.eleOption.setTransparency(this.ball,40) //保存中心點(diǎn)坐標(biāo) this.optionRangeViewCenterPoint = this.eleOption.getCenterPoint({offX:this.ballOffX,offY:this.ballOffY}) } }
2、dom對象操作類
eleOption.js
class EleOption{ //添加操作dom ID eleId constructor(eleId){ this.eleId = eleId } //獲取當(dāng)前關(guān)聯(lián)的el getCurrentEle(){ return document.getElementById(this.eleId) } //獲取el寬度 getEleWidth(el){ return el.offsetWidth } //獲取el高度 getEleHeight(el){ return el.offsetHeight } //設(shè)置背景顏色 setBackgroundColor(el,color){ el.style.backgroundColor = color } //設(shè)置寬度 setWidth(el,w){ el.style.width = w + 'px' } //設(shè)置高度 setHeight(el,h){ el.style.height = h + 'px' } //設(shè)置圓角 setCircle(el){ el.style.borderRadius = (this.getEleWidth(el) / 2.0 )+ 'px' } //設(shè)置絕對定位 setAbsolutePosition(el){ el.style.position = 'absolute' } //設(shè)置透明度 setTransparency(el,alpha){ el.style.opacity = alpha / 100 } //設(shè)置為父el中心位置 setSupCenter(el){ if(el.style.position != 'absolute'){ this.setAbsolutePosition(el) let superElWidth = this.getEleWidth(this.getSuperEl(el)) let superElHeight = this.getEleHeight(this.getSuperEl(el)) let width = this.getEleWidth(el) let height = this.getEleHeight(el) el.style.left = ((superElWidth - width) / 2.0) + 'px' el.style.top = ((superElHeight - height) / 2.0) + 'px' } } //設(shè)置中心位置 setCenter(el,point){ if(el.style.position != 'absolute'){ this.setAbsolutePosition(el) } el.style.left = point.x + 'px' el.style.top = point.y + 'px' } //獲取父類el getSuperEl(el){ return el.parentNode } //獲取el getElById(elId){ return document.getElementById(elId) } //創(chuàng)建el createEl(elId){ let el = document.createElement('div') if(elId){ el.setAttribute('id',elId) } return el } //添加子el addSubEl(superEl,subEl){ superEl.appendChild(subEl); } //取消交互 cancleUserInreface(el){ el.style.pointerEvents = 'none' } //添加move事件 addMoveEvent(el,ballOption,mcb,emcb){ //鼠標(biāo)進(jìn)入移動事件 el.onmousemove = (event)=>{ mcb(this.getMoveEventPoint(event,el),ballOption) } //鼠標(biāo)移出事件 el.onmouseout = (_)=>{ emcb(ballOption) } } //move事件監(jiān)聽 getMoveEventPoint(event,el){ let x = event.clientX - this.getSuperEl(el).offsetLeft let y = event.clientY - this.getSuperEl(el).offsetTop return {x,y} } //獲取中心點(diǎn) getCenterPoint(off){ let x = this.getSuperEl(this.getCurrentEle()).offsetLeft + (this.getEleWidth(this.getCurrentEle()) / 2.0) - off.offX let y = this.getSuperEl(this.getCurrentEle()).offsetTop + (this.getEleHeight(this.getCurrentEle()) / 2.0) - off.offY return {x,y} } }
3、用法
初始化控制操作類即可,綁定相對應(yīng)地 dom 進(jìn)行,控制球的初始化操作
<script src="../js/eleOption.js"></script> <script src="../js/ballOption.js"></script> <body> <div id="optionDiv"></div> <div id="car"> <img src="../source/car.jpeg" alt=""> </div> <div id="target"> <img src="../source/circle.jpeg" alt=""> </div> </body> <script> //初始化控制操作類即可 let ballOption = new BallOption('optionDiv',(angle)=>{ let targetEl = document.getElementById('target') targetEl.style.transform = 'rotate(' + angle + 'deg)' }) ballOption.createOptionView() </script>
總結(jié)與思考
代碼很簡單,其中通過計(jì)算來控制小球的位置移動,并將時時的鼠標(biāo)滑過的 point 轉(zhuǎn)換為旋轉(zhuǎn)角度供外界使用
以上就是JS實(shí)現(xiàn)簡單的操作桿旋轉(zhuǎn)示例詳解的詳細(xì)內(nèi)容,更多關(guān)于JS操作桿旋轉(zhuǎn)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JS中的every()對空數(shù)組總返回true原理分析
這篇文章主要為大家介紹了JS中的every()對空數(shù)組總返回true原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09JS實(shí)現(xiàn)一個可以當(dāng)鏡子照的?Button
這篇文章主要介紹了JS實(shí)現(xiàn)一個可以當(dāng)鏡子照的?Button的方法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03JS精髓原型鏈繼承及構(gòu)造函數(shù)繼承問題糾正
這篇文章主要為大家介紹了JS精髓原型鏈繼承及構(gòu)造函數(shù)繼承問題糾正,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06web?worker在項(xiàng)目中的使用學(xué)習(xí)為項(xiàng)目增加亮點(diǎn)
這篇文章主要為大家介紹了web?worker使用學(xué)習(xí)來為你的項(xiàng)目增加亮點(diǎn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07