唉~
唉!
唉~
这里我是封装成一个组件了,可以直接CV
<template>
<div id="joystick">
<div id="stick"></div>
</div>
</template>
<script setup>
import { onMounted } from "vue";
onMounted(() => {
// 标识当前触摸时的ID
let ID: number | null;
// 获取虚拟轮杆和轮杆的DOM元素
let joystick = document.getElementById("joystick");
let stick = document.getElementById("stick");
// 计算虚拟轮杆和轮杆的尺寸和位置参数
let joystickSize = joystick.offsetWidth; // 获取虚拟轮杆的宽度
let stickSize = stick.offsetWidth; // 获取轮杆的宽度
let maxDistance = joystickSize / 2 - stickSize / 2; // 计算轮杆最大可移动距离
let centerX = joystickSize / 2; // 计算虚拟轮杆的中心点横坐标
let centerY = joystickSize / 2; // 计算虚拟轮杆的中心点纵坐标
let currentX = centerX; // 初始化轮杆的当前横坐标为中心点横坐标
let currentY = centerY; // 初始化轮杆的当前纵坐标为中心点纵坐标
let angle = 0; // 初始化轮杆的当前角度为0
let distance = 0; // 初始化轮杆和中心点的距离为0
let degrees = 0; // 初始化需要展现的角度
// 更新轮杆的位置和角度
function updateStickPosition(x, y) {
// 计算轮杆和中心点的距离和角度
let dx = x - centerX; // 计算轮杆和中心点的横向距离
let dy = y - centerY; // 计算轮杆和中心点的纵向距离
distance = Math.min(Math.sqrt(dx * dx + dy * dy), maxDistance); // 计算轮杆和中心点的距离,取最小值
angle = (Math.atan2(dy, dx) * 180) / Math.PI; // 计算轮杆和中心点的角度,转换为角度值
// 计算轮杆的当前位置
currentX = centerX + distance * Math.cos((angle * Math.PI) / 180); // 计算轮杆的当前横坐标
currentY = centerY + distance * Math.sin((angle * Math.PI) / 180); // 计算轮杆的当前纵坐标
// 移动轮杆到当前位置
stick.style.transform = "translate(" + (currentX - centerX) + "px, " + (currentY - centerY) + "px)"; // 移动轮杆到当前位置
if (angle < 0) {
degrees = Math.floor((angle * 180) / Math.PI + 360);
} else {
degrees = Math.floor((angle * 180) / Math.PI);
}
console.log(degrees);
}
// 鼠标按下事件处理函数
joystick.addEventListener("mousedown", function (e) {
e.preventDefault(); // 阻止默认事件
const rect = joystick.getBoundingClientRect(); // 获取相对于视口信息
updateStickPosition(e.clientX - rect.left, e.clientY - rect.top);//更新轮杆的位置和角度
document.addEventListener("mousemove", onMouseMove); // 添加鼠标移动事件监听器
document.addEventListener("mouseup", onMouseUp); // 添加鼠标松开事件监听器
});
// 触摸屏按下事件处理函数
joystick.addEventListener("touchstart", function (e) {
e.preventDefault(); // 阻止默认事件
let touch = e.changedTouches[0]; // 获取第一个触摸点
const rect = joystick.getBoundingClientRect();// 获取相对于视口信息
updateStickPosition(touch.clientX - rect.left, touch.clientY - rect.top);//更新轮杆的位置和角度
document.addEventListener("touchmove", onTouchMove); // 添加触摸屏移动事件监听器
document.addEventListener("touchend", onTouchEnd); // 添加触摸屏松开事件监听器
});
// 鼠标移动事件处理函数
function onMouseMove(e) {
e.preventDefault(); // 阻止默认事件
const rect = joystick.getBoundingClientRect(); // 获取相对于视口信息
updateStickPosition(e.clientX - rect.left, e.clientY - rect.top);//更新轮杆的位置和角度
}
// 鼠标松开事件处理函数
function onMouseUp(e) {
e.preventDefault(); // 阻止默认事件
document.removeEventListener("mousemove", onMouseMove); // 移除鼠标移动事件监听器
document.removeEventListener("mouseup", onMouseUp); // 移除鼠标松开事件监听器
updateStickPosition(centerX, centerY); // 将轮杆移动回中心点
}
// 触摸屏移动事件处理函数
function onTouchMove(e) {
e.preventDefault(); // 阻止默认事件
for (let i = 0; i < e.changedTouches.length; i++) {
// 获取触摸点
let touch = e.changedTouches[i];
// 查早当前的出点
if (touch.identifier == ID) {
// 获取相对于视口信息
const rect = joystickDom.value.getBoundingClientRect();
//更新轮杆的位置和角度
updateStickPosition(touch.clientX - rect.left, touch.clientY - rect.top);
}
}
let touch = e.changedTouches[0];
const rect = joystick.getBoundingClientRect();
updateStickPosition(touch.clientX - rect.left, touch.clientY - rect.top);
}
// 触摸屏松开事件处理函数
function onTouchEnd(e) {
e.preventDefault(); // 阻止默认事件
document.removeEventListener("touchmove", onTouchMove); // 移除触摸屏移动事件监听器
document.removeEventListener("touchend", onTouchEnd); // 移除触摸屏松开事件监听器
updateStickPosition(centerX, centerY); // 将轮杆移动回中心点
ID = null; // 清除当前触摸的ID
}
});
</script>
<style scoped>
#joystick {
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
background-color: #ccc;
}
#stick {
position: absolute;
top: 50%;
left: 50%;
width: 50px;
height: 50px;
margin-top: -25px;
margin-left: -25px;
border-radius: 50%;
background-color: #f00;
}
</style>