虚拟轮杆实现触摸屏模拟游戏手柄

该文章展示了一个使用Vue编写的触摸交互组件,组件是一个虚拟轮杆,支持鼠标和触摸事件。当用户按下或触摸轮杆后,轮杆会跟随手指或鼠标移动,计算并更新其相对于中心点的位置和角度,松开时轮杆回归中心。代码包括事件监听、坐标和角度计算以及样式设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

唉~

唉!

唉~

这里我是封装成一个组件了,可以直接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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值