js vue 游戏滚轮方向键盘的实现

501 阅读1分钟

效果如图:

实现这样的效果,需要这三张图片:

话不多说直接上代码:

<template>
    <div class="roller">
        <div
            class="wheel"
            ref="wheel"
            @touchstart="touch($event)"
            @touchmove="touch($event)"
            @touchend="touchEnd($event)"
        >
            <img width="130" id="imgBox" :src="imgCurrent" />
            <div id="directionBtn" ref="directionBtn" style="position: absolute; z-index: 2;">
                <img width="80" :src="imgList[2]" id="son" />
            </div>
        </div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            // 半径
            radius: 0,
            d_radius: 0,
            // 中心点
            zoreX: 0,
            zoreY: 0,
            // 移动时距离
            moveX: 0,
            moveY: 0,
            // 中心环形一圈半径
            zoreOffset: 0,
            // 超出范围圆上点坐标
            dotX: 0,
            dotY: 0,
            // 方向按钮的初始位置
            directionLeft: "",
            directionTop: "",
            //通过监听turn的数值可以向后台发送对应的keycode,从而达到控制行动方向
            turn: 0, // 0表示在原点, 1表示右边,顺时针递增 
            imgCurrent: require("../../assets/roller/摇杆底_非焦点.png"),
            imgList: [
                require("../../assets/roller/摇杆底_非焦点.png"),
                require("../../assets/roller/摇杆底_焦点.png"),
                require("../../assets/roller/摇杆_方向.png")
            ]
            // wheel:
        };
    },
    mounted() {
        // 获取摇杆圆板的位置信息
        const wheelInfo = this.$refs.wheel;
        console.dir(wheelInfo.offsetLeft);
        const left = wheelInfo.offsetLeft;
        const top = wheelInfo.offsetTop;
        const width = wheelInfo.offsetWidth;
        const heigth = wheelInfo.offsetHeight;

        this.zoreOffset = width / 8; // 小一点比如 1/8, 可以增大触发面积
        this.zoreX = left + width / 2;
        this.zoreY = top + heigth / 2;

        console.log(this.zoreY, this.zoreX);
        // 获取摇杆圆板半径
        this.radius = width / 2;
        // 获取方向按钮的位置信息
        const directionInfo = this.$refs.directionBtn;
        const d_left = directionInfo.offsetLeft;
        const d_top = directionInfo.offsetTop;
        const d_width = directionInfo.offsetWidth;
        const d_heigth = directionInfo.offsetHeight;
        const d_X = d_left + d_width / 2;
        const d_Y = d_top + d_heigth / 2;

        // 获取方向按钮的半径
        this.d_radius = (d_width * 2) / 5; //这个因为是给了个图片,按钮的圆包含在图片里,所以只能取个大概,如果图片本身就是个圆那就更好说了直接d_width / 2

        // 设定中间按钮初始位置
        directionInfo.style.left = this.zoreX - d_X + "px";
        directionInfo.style.top = this.zoreY - d_Y + "px";
        this.directionLeft = directionInfo.style.left;
        this.directionTop = directionInfo.style.top;
        console.log(d_heigth + "ssssddes");

        console.dir(directionInfo);
    },
    methods: {
        touch(event) {
            var event = event || window.event;

            this.imgCurrent = this.imgList[1];

            switch (event.type) {
                case "touchstart":
                case "touchmove":
                //获取到当前手指的位置
                    this.moveX = event.touches[0].clientX;
                    this.moveY = event.touches[0].clientY;
                    // console.log(moveX, moveY)
                    break;
                case "touchend":
                    break;
            };
            
            // 获取手指的位置与中心点位置横纵坐标的差值
            let turnX = this.moveX - this.zoreX;
            let turnY = this.moveY - this.zoreY;
            
            // 通过判断圆心半径的数值与手指的位置信息的大小来判断是在哪个方位
            if (
                Math.abs(turnX) < this.zoreOffset &&
                Math.abs(turnY) < this.zoreOffset
            ) {
                this.turn = 0;  //在中心
            } else if (Math.abs(turnX) < this.zoreOffset) {
                this.turn = turnY > 0 ? 3 : 7;  // 3:下, 7:上
            } else if (Math.abs(turnY) < this.zoreOffset) {
                this.turn = turnX > 0 ? 1 : 5; // 1:右, 5:左
            } else {
                if (turnX > 0) {
                    // 在右边
                    this.turn = turnY > 0 ? 2 : 8; // 2:右下, 8:右上
                } else {
                    // 在左边
                    this.turn = turnY > 0 ? 4 : 6; // 4:坐下, 6:左上
                }
            }
            // this.imgCurrent = this.imgList[this.turn];
            // console.log(this.turn);

            // 控制移动
            this.moveBtn(event);
        },
        // 该方法是用来控制中间方向按钮移动
        moveBtn(e) {
            let event = e || window.event;
            // console.log(event);
            // 获取手指的位置
            let x = event.touches[0].clientX;
            let y = event.touches[0].clientY;

            // 限定范围
            let dx = Math.abs(x - this.zoreX); //横向距离绝对值
            let dy = Math.abs(y - this.zoreY); // 纵向距离绝对值

            // 计算角度用
            let non_dx = x - this.zoreX; //横向距离值
            let non_dy = y - this.zoreY; //纵向距离值
            let distance =
                Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)) + this.d_radius; // 计算出两者间的直线距离
            // console.log(non_dx, non_dy);

            if (distance > this.radius) {
                // 直线距离超出半径则在圆周上运动
                this.circularMotion(non_dx, non_dy);
                // 移动时按键跟随
                let directionInfo = this.$refs.directionBtn;
                directionInfo.style.left = this.dotX + "px";
                directionInfo.style.top = this.dotY + "px";
                return;
            }

            // 移动时按键跟随
            let directionInfo = this.$refs.directionBtn;
            directionInfo.style.left = x - directionInfo.offsetWidth / 2 + "px";
            directionInfo.style.top = y - directionInfo.offsetHeight / 2 + "px";
        },
        // 移动时超出半径部分的绕圆周运动
        circularMotion(non_dx, non_dy) {
            let angle;
            // if (non_dx > 0 && non_dy > 0) {
            //     // 第四象限
            //     angle = (360 * Math.atan(non_dy / non_dx)) / (2 * Math.PI);
            // } else if (non_dx > 0 && non_dy < 0) {
            //     // 第一象限
            //     angle = (360 * Math.atan(non_dy / non_dx)) / (2 * Math.PI);
            // } else if (non_dx < 0 && non_dy < 0) {
            //     // 第二象限
            //     angle =
            //         (360 * Math.atan(non_dy / non_dx)) / (2 * Math.PI) - 180;
            // } else if (non_dx < 0 && non_dy > 0) {
            //     // 第三象限
            //     angle =
            //         (360 * Math.atan(non_dy / non_dx)) / (2 * Math.PI) - 180;
            // }

            //以上代码简化
            if (non_dx > 0) {
                // 第一和第四象限
                angle = (360 * Math.atan(non_dy / non_dx)) / (2 * Math.PI);
            } else if (non_dx < 0) {
                // 第二和第三象限
                angle =
                    (360 * Math.atan(non_dy / non_dx)) / (2 * Math.PI) - 180;
            }

            // 通过角度获取圆上点坐标  算出的坐标需要加上背景中心点坐标再减去按钮的半径
            this.dotX =
                (this.radius - this.d_radius) *
                    Math.cos((angle * Math.PI) / 180) +
                this.zoreX -
                this.$refs.directionBtn.offsetHeight / 2;
            this.dotY =
                (this.radius - this.d_radius) *
                    Math.sin((angle * Math.PI) / 180) +
                this.zoreY -
                this.$refs.directionBtn.offsetHeight / 2;
            console.log(this.dotX, this.dotY);
            // return dotX, dotY;
        },
        touchEnd(event) {
            // 抬起归位
            this.imgCurrent = this.imgList[0];
            this.turn = 0;
            this.$refs.directionBtn.style.left = this.directionLeft;
            this.$refs.directionBtn.style.top = this.directionTop;
        }
    }
};
</script>
<style scoped>
.wheel {
    width: 130px;
    height: 130px;
    background-color: black;
    position: relative;
}
#imgBox {
    position: absolute;
    z-index: 1;
    left: 0;
}
#directionBtn {
    overflow: hidden;
    height: 80px;
    width: 80px;
    position: absolute;
    z-index: 2;
}
img {
    vertical-align: middle;
}
</style>

这个方法思路是将判断方向与中间滑块的运动分开来了。