用 vue3 实现一个元宇宙/游戏操作摇杆 (输出弧度/角度/方向)

458 阅读1分钟

效果

image.png

image.png

上代码

<template>
  <div>
    <canvas
      ref="canvas"
      @mousedown="startDragging"
      @touchstart="startDragging"
      @mousemove="drag"
      @touchmove="drag"
      @mouseup="stopDragging"
      @touchend="stopDragging"
    ></canvas>
    {{ direction }}
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue';

const canvas = ref<HTMLCanvasElement | null>(null);
const context = ref<CanvasRenderingContext2D | null>(null);
const width = 200;
const height = 200;
const radius = width / 4;
const centerX = width / 2;
const centerY = height / 2;
let x = centerX;
let y = centerY;
let isDragging = false;
const direction = ref<number | null>(null);

function draw() {
  if (!context.value || !canvas.value) return;
  context.value.clearRect(0, 0, canvas.value.width, canvas.value.height);

  // 绘制摇杆底座
  context.value.beginPath();
  context.value.arc(
    canvas.value.width / 2,
    canvas.value.height / 2,
    radius * 1.5,
    0,
    2 * Math.PI,
    false,
  );
  context.value.fillStyle = '#6464641a';
  context.value.fill();
  context.value.lineWidth = 2;
  context.value.strokeStyle = 'rgba(100,100,100,0.8)';
  context.value.stroke();

  // 绘制四个箭头
  const arrowLength = 6;
  const arrowAngle = Math.PI / 6;
  context.value.save();
  context.value.translate(centerX, centerY);
  for (let i = 0; i < 4; i++) {
    context.value.beginPath();
    context.value.rotate((Math.PI / 2) * i);
    // context.value.moveTo(radius - arrowLength, 0);
    context.value.lineTo(radius * 1.4, 0);
    context.value.lineTo(
      radius * 1.4 - arrowLength * Math.cos(arrowAngle),
      arrowLength * Math.sin(arrowAngle),
    );
    context.value.moveTo(radius * 1.4, 0);
    context.value.lineTo(
      radius * 1.4 - arrowLength * Math.cos(arrowAngle),
      -arrowLength * Math.sin(arrowAngle),
    );
    // context.value.strokeStyle = '#c6c9cd';
    context.value.strokeStyle = 'rgba(100,100,100,1)';
    context.value.stroke();
  }
  context.value.restore();

  // 绘制内圈背景
  context.value.beginPath();
  context.value.arc(
    canvas.value.width / 2,
    canvas.value.height / 2,
    radius * 1.2,
    0,
    2 * Math.PI,
    false,
  );
  context.value.fillStyle = 'rgba(100,100,100,0.4)';
  context.value.fill();
  context.value.lineWidth = 0;

  // 绘制内圈
  context.value.beginPath();
  context.value.arc(
    canvas.value.width / 2,
    canvas.value.height / 2,
    radius / 1.6,
    0,
    2 * Math.PI,
    false,
  );
  context.value.lineWidth = 1;
  context.value.strokeStyle = 'rgba(100,100,100,1)';
  context.value.stroke();

  // 绘制中心圆圈
  context.value.beginPath();
  context.value.arc(x, y, radius / 2.2, 0, 2 * Math.PI, false);
  context.value.fillStyle = '#fff';
  context.value.fill();
  //   context.value.lineWidth = 2;
  //   context.value.strokeStyle = '#fff';
  //   context.value.stroke();
  console.log('弧度:', getDirection());
  console.log('角度:', getDirection2());
  console.log('方向:', getDirection3());
  console.log('-------------');
}

function getDirection() {
  const deltaX = x - centerX;
  const deltaY = y - centerY;
  let angle = Math.atan2(deltaY, deltaX);

  if (angle < 0) {
    angle += 2 * Math.PI;
  }
  return angle;
}

function getDirection2() {
  const deltaX = x - centerX;
  const deltaY = y - centerY;
  let angle = Math.atan2(deltaY, deltaX);

  // 将弧度转换为角度
  angle *= 180 / Math.PI;
  let direction = '';

  if (angle > -135 && angle < -45) {
    direction = 'up';
  } else if (angle > -45 && angle < 45) {
    direction = 'right';
  } else if (angle > 45 && angle < 135) {
    direction = 'down';
  } else {
    direction = 'left';
  }
  return direction;
}

function getDirection3() {
  const deltaX = x - centerX;
  const deltaY = y - centerY;
  let angle = Math.atan2(deltaY, deltaX);

  if (angle < 0) {
    angle += 2 * Math.PI;
  }

  const direction = (angle * 180) / Math.PI;

  return direction;
}
function startDragging(e: MouseEvent | TouchEvent) {
  isDragging = true;
  e.preventDefault();
}

function drag(e: any) {
  if (!canvas.value) return;

  if (isDragging) {
    if (e.type === 'touchmove') {
      x = e.touches[0].clientX - canvas.value.offsetLeft;
      y = e.touches[0].clientY - canvas.value.offsetTop;
    } else {
      x = e.clientX - canvas.value.offsetLeft;
      y = e.clientY - canvas.value.offsetTop;
    }

    // 限制摇杆的移动范围
    const distance = Math.sqrt(
      Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2),
    );
    if (distance > radius) {
      const angle = Math.atan2(y - centerY, x - centerX);
      x = centerX + radius * Math.cos(angle);
      y = centerY + radius * Math.sin(angle);
    }

    direction.value = getDirection();

    draw();
  }
}

function stopDragging() {
  isDragging = false;
  x = centerX;
  y = centerY;
  direction.value = null;
  draw();
}

// 初始化画布和绘制摇杆
function init() {
  if (!canvas.value) return;
  canvas.value.width = width;
  canvas.value.height = height;
  context.value = canvas.value.getContext('2d');
  draw();
}
onMounted(() => {
  init();
});
</script>

<style lang="less" scoped>
div {
  width: 100%;
  height: 100vh;
  color: #fff;
  background: url(data:image/jpeg;base64,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)
    no-repeat;
  background-size: 100% 100%;

  canvas {
    // border: 1px solid;
  }
}
</style>