<template>
  <view 
    class="floating-drag"
    :style="{
      left: buttonPosition.left + 'px',
      right: buttonPosition.right + 'px',
      bottom: buttonPosition.bottom + 'px',
      width: width + 'rpx',
      height: height + 'rpx',
      display: visible ? 'block' : 'none'
    }"
    @touchstart="touchStart"
    @touchmove="touchMove"
    @touchend="touchEnd"
    @click="handleClick"
    v-if="visible"
  >
    <slot>
      <!-- Default content if no slot is provided -->
      <view class="default-btn">
        <text>按钮</text>
      </view>
    </slot>
  </view>
</template>

<script>
export default {
  name: 'FloatingDrag',
  props: {
    // 初始位置
    initialPosition: {
      type: Object,
      default: () => ({
        left: 'auto',
        right: 0,
        bottom: '20%'
      })
    },
    // 组件尺寸
    width: {
      type: [Number, String],
      default: 120
    },
    height: {
      type: [Number, String],
      default: 120
    },
    // 是否显示
    visible: {
      type: Boolean,
      default: true
    },
    // 点击事件
    onClick: {
      type: Function,
      default: null
    }
  },
  data() {
    return {
      // 悬浮按钮位置
      buttonPosition: {
        left: 'auto',
        right: 0,
        bottom: '20%',
      },
      // 触摸开始位置
      startX: 0,
      startY: 0,
      // 屏幕宽度和高度
      screenWidth: 0,
      screenHeight: 0,
      // 初始位置记录，用于计算拖动
      initialLeft: 0,
      initialBottom: 0,
      // 是否正在更新位置，用于防止频繁更新
      isUpdatingPosition: false,
    };
  },
  created() {
    // 使用传入的初始位置
    this.buttonPosition = { ...this.initialPosition };
  },
  watch: {
    initialPosition: {
      handler(newVal) {
        this.buttonPosition = { ...newVal };
      },
      immediate: true,
    },
  },
  mounted() {
    // 获取屏幕宽度和高度
    uni.getSystemInfo({
      success: (res) => {
        this.screenWidth = res.windowWidth;
        this.screenHeight = res.windowHeight;
      },
    });
  },
  methods: {
    // 触摸开始
    touchStart(e) {
      const touch = e.touches[0];
      this.startX = touch.clientX;
      this.startY = touch.clientY;

      // 记录初始位置，用于计算移动距离
      if (this.buttonPosition.right !== 'auto') {
        // 如果是靠右定位，记录当前位置但不立即改变显示位置
        this.initialLeft = this.screenWidth - parseFloat(this.width) / 2;
      } else {
        this.initialLeft = parseFloat(this.buttonPosition.left);
      }

      // 如果bottom是百分比，转换为具体像素值
      if (typeof this.buttonPosition.bottom === 'string' && this.buttonPosition.bottom.includes('%')) {
        const percentage = parseFloat(this.buttonPosition.bottom) / 100;
        this.initialBottom = this.screenHeight * percentage;
      } else {
        this.initialBottom = parseFloat(this.buttonPosition.bottom);
      }
    },

    // 触摸移动
    touchMove(e) {
      // 阻止默认行为，防止页面滚动
      e.preventDefault && e.preventDefault();
      e.stopPropagation && e.stopPropagation();

      const touch = e.touches[0];

      // 计算移动距离
      const deltaX = touch.clientX - this.startX;
      const deltaY = touch.clientY - this.startY;

      // 使用初始位置计算新位置，避免累积误差
      let newLeft = this.initialLeft + deltaX;
      let newBottom = this.initialBottom - deltaY; // 注意：y轴方向是相反的

      // 获取按钮实际宽度（将rpx转换为px）
      const buttonWidthPx = parseFloat(this.width) / 750 * this.screenWidth;
      
      // 确保按钮不超出屏幕边界
      if (newLeft < 0) {
        newLeft = 0;
      } else if (newLeft > this.screenWidth - buttonWidthPx) {
        newLeft = this.screenWidth - buttonWidthPx;
      }

      // 确保按钮不超出屏幕垂直边界
      if (newBottom < 20) {
        newBottom = 20;
      } else if (newBottom > this.screenHeight - buttonWidthPx) {
        newBottom = this.screenHeight - buttonWidthPx;
      }

      // 使用节流方式更新位置，避免过于频繁的更新
      if (!this.isUpdatingPosition) {
        this.isUpdatingPosition = true;

        // 更新位置 - 第一次移动时才真正改变right为auto
        this.buttonPosition = {
          left: newLeft,
          right: 'auto',
          bottom: newBottom,
        };

        // 使用setTimeout代替requestAnimationFrame，在微信小程序中更兼容
        setTimeout(() => {
          this.isUpdatingPosition = false;
        }, 16); // 约等于60fps的刷新率
      }
    },

    // 触摸结束，实现吸附效果
    touchEnd() {
      // 确保不再有待处理的更新
      this.isUpdatingPosition = false;

      // 获取按钮实际宽度（将rpx转换为px）
      const buttonWidthPx = parseFloat(this.width) / 750 * this.screenWidth;
      const buttonCenter = this.buttonPosition.left + buttonWidthPx / 2; // 按钮中心位置
      
      const halfScreen = this.screenWidth / 2;

      // 判断是吸附到左边还是右边
      if (buttonCenter < halfScreen) {
        // 吸附到左边
        this.buttonPosition = {
          left: 0,
          right: 'auto',
          bottom: this.buttonPosition.bottom,
        };
      } else {
        // 吸附到右边
        this.buttonPosition = {
          left: 'auto',
          right: 0,
          bottom: this.buttonPosition.bottom,
        };
      }
      
      // 触发位置变更事件
      this.$emit('position-change', { ...this.buttonPosition });
    },
    
    // 处理点击事件
    handleClick() {
      this.$emit('click');
      if (this.onClick) {
        this.onClick();
      }
    }
  }
};
</script>

<style lang="scss" scoped>
.floating-drag {
  position: fixed;
  z-index: 999;
  transition: all 0.3s ease;
  
  .default-btn {
    width: 100%;
    height: 100%;
    background-color: #4cd964;
    border-radius: 50%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    border: 4rpx solid #fff;
    box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.2);
    
    text {
      color: #ffffff;
      font-size: 34rpx;
      text-align: center;
      font-weight: 500;
      padding: 0 10rpx;
      line-height: 1.2;
    }
  }
}
</style> 