素材

Untitled

Untitled

实现

//index.vue
<template>
  <view class="compass-wrapper center-item">
    <image
      class="compassimg"
      :style="`transform:rotate(${90 - deg}deg)`"
      src="/static/home/compass.png"
      mode="aspectFill"
      lazy-load="false"
    />
    <image class="compassimg2" src="/static/home/cursor.png" mode="aspectFill" lazy-load="false" />
  </view>
</template>
<script setup>
import { useCompass } from '@/hooks/useCompass';
const { deg } = useCompass();
</script>

<style lang="scss" scoped>
.compass-wrapper {
  position: relative;
  width: 100px;
  height: 100px;
  .compassimg {
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    top: 0;
    z-index: 50;
    transition: all 0.3s;
  }

  .compassimg2 {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 99;
    width: 17px;
    height: 62px;
  }
}
</style>
//useCompass.js
import { ref } from "vue";
import { onShow, onHide } from "@dcloudio/uni-app";
export const useCompass = () => {
  let deg = ref(0);
  let lastDeg = ref(0);
  let isSouth = ref(false);
  // 计算指南针旋转角度
  const getRotationDifference = (current, last) => {
    let diff = current - last;
    if (diff > 180) {
      diff -= 360;
    } else if (diff < -180) {
      diff += 360;
    }
    return diff;
  };

  const callback = (res) => {
    let rotateDeg = res?.direction.toFixed(0);
    if (rotateDeg >= 150 && rotateDeg <= 210) {
      isSouth.value = true;
    } else {
      isSouth.value = false;
    }
    let rotationDifference = getRotationDifference(rotateDeg, lastDeg.value);
    deg.value += rotationDifference; // 用差值来更新角度
    lastDeg.value = rotateDeg; // 更新上一次的角度记录
  };

  onShow(() => {
    uni.onCompassChange(callback);
  });
  onHide(() => {
    uni.offCompassChange(callback);
  });

  return {
    deg,
    isSouth,
  };
};