vue实现双摇杆
双摇杆实现思路
双摇杆通常用于游戏或交互式应用中,一个摇杆控制角色移动,另一个控制视角或攻击方向。Vue中可以通过监听触摸或鼠标事件实现。
基础HTML结构
创建两个摇杆的DOM元素,分别用不同类名标识:
<template>
<div class="joystick-container">
<div class="joystick-movement" ref="movementJoystick"></div>
<div class="joystick-aiming" ref="aimingJoystick"></div>
</div>
</template>
样式设置
使用CSS定位摇杆元素,设置基本样式:
.joystick-container {
position: relative;
width: 100%;
height: 100vh;
}
.joystick-movement, .joystick-aiming {
position: absolute;
width: 100px;
height: 100px;
border-radius: 50%;
background: rgba(0, 0, 0, 0.3);
}
.joystick-movement {
bottom: 50px;
left: 50px;
}
.joystick-aiming {
bottom: 50px;
right: 50px;
}
摇杆逻辑实现
在Vue组件中实现摇杆控制逻辑:

export default {
mounted() {
this.initJoystick(this.$refs.movementJoystick, 'movement');
this.initJoystick(this.$refs.aimingJoystick, 'aiming');
},
methods: {
initJoystick(element, type) {
const stick = document.createElement('div');
stick.className = 'joystick-handle';
element.appendChild(stick);
const rect = element.getBoundingClientRect();
const center = {
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
};
const handleMove = (e) => {
const clientX = e.touches ? e.touches[0].clientX : e.clientX;
const clientY = e.touches ? e.touches[0].clientY : e.clientY;
const deltaX = clientX - center.x;
const deltaY = clientY - center.y;
const distance = Math.min(Math.sqrt(deltaX * deltaX + deltaY * deltaY), rect.width / 2);
const angle = Math.atan2(deltaY, deltaX);
const x = distance * Math.cos(angle);
const y = distance * Math.sin(angle);
stick.style.transform = `translate(${x}px, ${y}px)`;
// 根据type分发不同事件
const event = new CustomEvent(`${type}-joystick`, {
detail: {
x: x / (rect.width / 2),
y: y / (rect.height / 2)
}
});
window.dispatchEvent(event);
};
const handleEnd = () => {
stick.style.transform = 'translate(0, 0)';
window.dispatchEvent(new CustomEvent(`${type}-joystick`, {
detail: { x: 0, y: 0 }
}));
};
element.addEventListener('touchstart', (e) => {
e.preventDefault();
handleMove(e);
document.addEventListener('touchmove', handleMove);
document.addEventListener('touchend', handleEnd, { once: true });
});
element.addEventListener('mousedown', () => {
document.addEventListener('mousemove', handleMove);
document.addEventListener('mouseup', handleEnd, { once: true });
});
}
}
}
摇杆手柄样式
添加摇杆手柄的CSS样式:
.joystick-handle {
position: absolute;
width: 40px;
height: 40px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.7);
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
}
事件监听使用
在其他组件中监听摇杆事件:

mounted() {
window.addEventListener('movement-joystick', (e) => {
console.log('移动摇杆:', e.detail);
});
window.addEventListener('aiming-joystick', (e) => {
console.log('瞄准摇杆:', e.detail);
});
}
摇杆限制优化
添加摇杆移动范围限制,防止手柄超出摇杆区域:
const distance = Math.min(
Math.sqrt(deltaX * deltaX + deltaY * deltaY),
rect.width / 2
);
移动平滑处理
添加缓动效果使摇杆移动更平滑:
stick.style.transition = distance === 0 ? 'transform 0.2s ease-out' : 'none';
销毁事件监听
在组件销毁时移除事件监听:
beforeDestroy() {
window.removeEventListener('movement-joystick');
window.removeEventListener('aiming-joystick');
}






