134 lines
3.9 KiB
JavaScript
134 lines
3.9 KiB
JavaScript
class Joystick {
|
||
|
||
// 元素id,最大移动距离
|
||
constructor(stickID, direction, callback) {
|
||
this.id = stickID;
|
||
this.maxDistance = 64;
|
||
this.direction = direction;
|
||
this.callback = callback;
|
||
this.time = null
|
||
this.stick = document.getElementById(stickID);
|
||
|
||
// 开始拖动的位置,用于计算偏移量
|
||
this.dragStart = null;
|
||
|
||
// 如果存在多个操纵手柄,则跟踪触摸标识符
|
||
this.touchId = null;
|
||
|
||
this.active = false;
|
||
this.EventListener();
|
||
}
|
||
|
||
handleDown(event) {
|
||
|
||
this.active = true;
|
||
this.stick.style.transition = '0s';
|
||
|
||
// 阻止默认事件
|
||
event.preventDefault();
|
||
|
||
// 记录初始点击的坐标
|
||
if (event.changedTouches) {
|
||
this.dragStart = { x: event.changedTouches[0].clientX, y: event.changedTouches[0].clientY };
|
||
} else {
|
||
this.dragStart = { x: event.clientX, y: event.clientY };
|
||
}
|
||
|
||
// console.log("event: ", event);
|
||
// console.log("event.changedTouches: ", event.changedTouches);
|
||
|
||
// 记录点击的id
|
||
if (event.changedTouches) {
|
||
this.touchId = event.changedTouches[0].identifier;
|
||
}
|
||
|
||
}
|
||
handleMove(event) {
|
||
if (!this.active) return;
|
||
if (event.changedTouches && this.touchId != event.changedTouches[0].identifier) return;
|
||
|
||
// 处理多点触控
|
||
if (event.changedTouches) {
|
||
for (let i = 0; i < event.changedTouches.length; i++) {
|
||
if (this.touchId == event.changedTouches[i].identifier) {
|
||
event.clientX = event.changedTouches[i].clientX;
|
||
event.clientY = event.changedTouches[i].clientY;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 计算 x 轴距离
|
||
const xDiff = event.clientX - this.dragStart.x;
|
||
// 计算 y 轴距离
|
||
const yDiff = event.clientY - this.dragStart.y;
|
||
|
||
// 计算 角度
|
||
const angle = Math.atan2(yDiff, xDiff);
|
||
|
||
// 计算 距离
|
||
const distance = Math.min(this.maxDistance, Math.hypot(xDiff, yDiff));
|
||
|
||
|
||
// 计算 x,y 的新位置
|
||
const xPosition = distance * Math.cos(angle);
|
||
const yPosition = distance * Math.sin(angle);
|
||
|
||
if (this.time && (Date.now() - this.time) < 30) return
|
||
this.time = Date.now()
|
||
|
||
if (this.direction == "x") {
|
||
// console.log("xPosition: ", Math.sign(xPosition));
|
||
// 左边 0 ~ -64 -1 3
|
||
if (xPosition < 0) {
|
||
if (xPosition < -63) {
|
||
console.log("左边: ", xPosition);
|
||
this.callback(3)
|
||
}
|
||
// 右边 1 4
|
||
} else if (xPosition > 0){
|
||
if (xPosition > 63) {
|
||
console.log("右边: ", xPosition);
|
||
this.callback(4)
|
||
}
|
||
}
|
||
// 将图片移动到新位置
|
||
this.stick.style.transform = `translate3d(${xPosition}px,0px, 0px)`;
|
||
// this.callback(Math.sign(xPosition) == -1 ? 3 : 4)
|
||
} else {
|
||
console.log("yPosition: ", yPosition);
|
||
this.stick.style.transform = `translate3d(0px,${yPosition}px, 0px)`;
|
||
this.callback(Math.sign(yPosition) == -1 ? 1 : 2, Math.round(255 * Math.round(Math.abs(yPosition)) / 64))
|
||
}
|
||
|
||
|
||
}
|
||
handleUp(event) {
|
||
|
||
if (!this.active) return;
|
||
if (event.changedTouches && this.touchId != event.changedTouches[0].identifier) return;
|
||
|
||
this.active = false;
|
||
|
||
// console.log("3 handleUp ==== ", this.active);
|
||
|
||
|
||
this.stick.style.transition = '.2s';
|
||
this.stick.style.transform = `translate3d(0px, 0px, 0px)`;
|
||
this.touchId = null;
|
||
|
||
this.callback(0, 0)
|
||
}
|
||
EventListener() {
|
||
// 鼠标 & 手指 按下
|
||
this.stick.addEventListener('mousedown', this.handleDown.bind(this));
|
||
this.stick.addEventListener('touchstart', this.handleDown.bind(this));
|
||
|
||
// 鼠标 & 手指 移动
|
||
document.addEventListener('mousemove', this.handleMove.bind(this), { passive: false });
|
||
document.addEventListener('touchmove', this.handleMove.bind(this), { passive: false });
|
||
|
||
// 鼠标 & 手指 松开
|
||
document.addEventListener('mouseup', this.handleUp.bind(this));
|
||
document.addEventListener('touchend', this.handleUp.bind(this));
|
||
}
|
||
} |