JS实现简单的操作杆旋转示例详解

 更新时间:2023年01月15日 14:36:25   作者:头疼脑胀的代码搬运工  
这篇文章主要为大家介绍了JS实现简单的操作杆旋转示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

一、实现效果

JS 简单的操作杆旋转实现

首先说明一下,请直接忽略背景图,这里主要实现的是杆旋转控制方向盘旋转。

鼠标移出控制区域,控制球复位

二、组成部分

创建 ballOption.js 文件,用以绑定控制球指定 dom,并初始化相关操作

创建 eleOption.js 文件,用以实现一些频繁的 dom 操作

主要是通过鼠标滑动事件控制“控制球”位置更改及获取以屏幕上方向为0度的角度计算,来控制“方向盘”进行旋转。

目标

1、监听鼠标滑动的事件,并判断 eventpoint 是否进入到控制球,如果进入,控制小球随着鼠标进行移动。

2、鼠标划出控制区域,控制球复位,旋转角度归零。

3、判断鼠标 point 点位置,通过反三角函数获取角度。

4、暴露控制球与控制区域中心形成的旋转角度,触发外界事件(方向盘旋转)

三、代码实现

1、操作控制

ballOption.js 文件

class BallOption{
    //添加操作dom ID
    eleId
    //el操作对象
    eleOption
    //控制球对象
    ball
    //控制球尺寸
    ballWidth
    ballHeight
    ballOffX
    ballOffY
    //是否触碰过控制球
    isTouchedBall = false
    //控制区域
    optionRangeView
    optionRangeViewCenterPoint
    //上一次角度
    lastDeg
    //角度回调
    angleCallBack
    //初始化操作
    constructor(eleId,angleCallBack){
        this.eleId = eleId
        this.angleCallBack = angleCallBack
        this.eleOption = new EleOption(eleId)
    }
    //创建操作框
    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)
    }
    //控制球随鼠标滚
    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
    }
    //鼠标移出事件
    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)
        }
    }
    //计算角度
    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)
        //保存中心点坐标
        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
    }
    //获取当前关联的el
    getCurrentEle(){
        return document.getElementById(this.eleId)
    }
    //获取el宽度
    getEleWidth(el){
        return el.offsetWidth
    }
    //获取el高度
    getEleHeight(el){
        return el.offsetHeight
    }
    //设置背景颜色
    setBackgroundColor(el,color){
        el.style.backgroundColor = color
    }
    //设置宽度
    setWidth(el,w){
        el.style.width = w + 'px'
    }
    //设置高度
    setHeight(el,h){
        el.style.height = h + 'px'
    }
    //设置圆角
    setCircle(el){
        el.style.borderRadius = (this.getEleWidth(el) / 2.0 )+ 'px'
    }
    //设置绝对定位
    setAbsolutePosition(el){
        el.style.position = 'absolute'
    }
    //设置透明度
    setTransparency(el,alpha){
        el.style.opacity = alpha / 100
    }
    //设置为父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'
        }
    }
    //设置中心位置
    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)
    }
    //创建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){
        //鼠标进入移动事件
        el.onmousemove = (event)=>{
            mcb(this.getMoveEventPoint(event,el),ballOption)
        }
        //鼠标移出事件
        el.onmouseout = (_)=>{
            emcb(ballOption)
        }
    }
    //move事件监听
    getMoveEventPoint(event,el){
        let x = event.clientX - this.getSuperEl(el).offsetLeft
        let y = event.clientY - this.getSuperEl(el).offsetTop
        return {x,y}
    }
    //获取中心点
    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、用法

初始化控制操作类即可,绑定相对应地 dom 进行,控制球的初始化操作

<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>

总结与思考

代码很简单,其中通过计算来控制小球的位置移动,并将时时的鼠标滑过的 point 转换为旋转角度供外界使用

以上就是JS实现简单的操作杆旋转示例详解的详细内容,更多关于JS操作杆旋转的资料请关注脚本之家其它相关文章!

相关文章

  • 前端算法题解 leetcode50-Pow(x, n)

    前端算法题解 leetcode50-Pow(x, n)

    这篇文章主要为大家介绍了前端算法题解 leetcode50-Pow(x, n)示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • JS前端使用canvas编写一个签名板

    JS前端使用canvas编写一个签名板

    这篇文章主要为大家介绍了JS前端使用canvas编写一个签名板实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • 微信小程序 navbar实例详解

    微信小程序 navbar实例详解

    这篇文章主要介绍了微信小程序 navbar实例详解的相关资料,需要的朋友可以参考下
    2017-05-05
  • JS中的every()对空数组总返回true原理分析

    JS中的every()对空数组总返回true原理分析

    这篇文章主要为大家介绍了JS中的every()对空数组总返回true原理分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • JS实现一个可以当镜子照的 Button

    JS实现一个可以当镜子照的 Button

    这篇文章主要介绍了JS实现一个可以当镜子照的 Button的方法示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • JS精髓原型链继承及构造函数继承问题纠正

    JS精髓原型链继承及构造函数继承问题纠正

    这篇文章主要为大家介绍了JS精髓原型链继承及构造函数继承问题纠正,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 微信小程序 rpx 尺寸单位详细介绍

    微信小程序 rpx 尺寸单位详细介绍

    这篇文章主要介绍了微信小程序 rpx尺寸单位以及样式详细介绍的相关资料,有效的帮助大家开发微信小程序,避免手机尺寸问题,需要的朋友可以参考下
    2016-10-10
  • web worker在项目中的使用学习为项目增加亮点

    web worker在项目中的使用学习为项目增加亮点

    这篇文章主要为大家介绍了web worker使用学习来为你的项目增加亮点,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • js简单封装监听快捷键对象示例及使用

    js简单封装监听快捷键对象示例及使用

    这篇文章主要为大家介绍了js简单封装监听快捷键对象及使用示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • 关于C++ TpeScript系列的泛型

    关于C++ TpeScript系列的泛型

    这篇文章将从C++模版要解决的问题出发,引出TS泛型要解决的问题,并简答介绍一些稍微高级的使用场景的相关资料,需要的朋友可以参考一下
    2021-10-10

最新评论