uniapp浮动按钮

本文介绍了在uniapp中实现浮动按钮的三种方式:可拖拽的组件(支持渐变色、大小、图标,限制边界)、直接在页面中编码实现,以及带有外圈发光动画和颜色变化的纯CSS发光按钮。提供了完整的代码示例和调用方法。

作者:zhuge··预计阅读 30 分钟·518 阅读·0 评论
uniapp浮动按钮

第一个是组件 第二个是直接在页面 第三个是发光按钮

#####是组件

<template>
  <view class="container">
    <view 
      class="float-button"
      :style="{
        top: buttonTop + 'px',
        left: buttonLeft + 'px',
        background: gradientBackground,
        width: buttonSize + 'px',
        height: buttonSize + 'px'
      }"
      @touchstart="handleTouchStart"
      @touchmove="handleTouchMove"
      @touchend="handleTouchEnd"
      @click="handleClick"
    >
      <image class="button-icon" :src="buttonIconSrc" />
    </view>
  </view>
</template>

<script>
export default {
  props: {
    gradientColors: {
      type: Array,
      default: () => ['#ff6b6b', '#f06595']
    },
    buttonSize: {
      type: Number,
      default: 60
    },
    buttonIconSrc: {
      type: String,
      default: '/static/icon/add.png'
    }
  },
  data() {
    const screenInfo = uni.getSystemInfoSync();
    const screenWidth = screenInfo.windowWidth;
    const screenHeight = screenInfo.windowHeight;

    return {
      buttonTop: screenHeight - this.buttonSize - 30, // 30 是距离底部的间距
      buttonLeft: screenWidth - this.buttonSize - 30, // 30 是距离右侧的间距
      startX: 0,
      startY: 0,
      isDragging: false
    };
  },
  computed: {
    gradientBackground() {
      return `linear-gradient(45deg, ${this.gradientColors.join(', ')})`;
    }
  },
  methods: {
    handleTouchStart(event) {
      this.startX = event.touches[0].clientX;
      this.startY = event.touches[0].clientY;
      this.isDragging = true;
    },
    handleTouchMove(event) {
      if (this.isDragging) {
        const touch = event.touches[0];
        const deltaX = touch.clientX - this.startX;
        const deltaY = touch.clientY - this.startY;

        let newTop = this.buttonTop + deltaY;
        let newLeft = this.buttonLeft + deltaX;

        const screenInfo = uni.getSystemInfoSync();
        const screenWidth = screenInfo.windowWidth;
        const screenHeight = screenInfo.windowHeight;

        if (newTop < 0) newTop = 0;
        if (newTop + this.buttonSize > screenHeight) newTop = screenHeight - this.buttonSize;
        if (newLeft < 0) newLeft = 0;
        if (newLeft + this.buttonSize > screenWidth) newLeft = screenWidth - this.buttonSize;

        this.buttonTop = newTop;
        this.buttonLeft = newLeft;

        this.startX = touch.clientX;
        this.startY = touch.clientY;
      }
    },
    handleTouchEnd() {
      this.isDragging = false;
    },
    handleClick() {
      console.log('按钮被点击');
      // 触发父组件的 click 事件
      this.$emit('click');
    }
  }
};
</script>

<style scoped>
/* .container {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
} */

.float-button {
  position: absolute;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 50%;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2), 0 2px 4px rgba(0, 0, 0, 0.1) inset, 0 -1px 1px rgba(255, 255, 255, 0.3) inset;
  cursor: pointer;
  user-select: none;
  touch-action: none;
}

.button-icon {
  width: 60%;
  height: 60%;
  object-fit: contain;
}
</style>

使用

<template>
  <view class="page-container">
    <custom-float-button
      :gradient-colors="['#ff7f50', '#ff4500']"
      :button-size="80"
  :button-icon-src="'/static/icon/add.png'"
      @click="handleButtonClick1"
    ></custom-float-button>
    
    <custom-float-button
      :gradient-colors="['#6495ed', '#00bfff']"
      :button-size="80"
  :button-icon-src="'/static/icon/add.png'"
      @click="handleButtonClick2"
    ></custom-float-button>


	<custom-float-button
	  :gradient-colors="['#ff7f50', '#ff4500']"
	  :button-size="50"
	  :button-icon-src="'/static/icon/add.png'"
	   @click="handleButtonClick2"
	></custom-float-button>
  </view>
</template>

<script>
import CustomFloatButton from '@/components/draggable-button/draggable-button.vue'

export default {
  components: {
    CustomFloatButton
  },
  data() {
    return {};
  },
 methods: {
    handleButtonClick1() {
      console.log('浮动按钮被点击');
      // 这里可以执行更多的逻辑,例如跳转到另一个页面
    },
	handleButtonClick2() {
	  console.log('浮动按钮22222222222被点击');
	  // 这里可以执行更多的逻辑,例如跳转到另一个页面
	}
  }
};
</script>

#####页面

<template>  
  <view class="container">  
    <view  
      class="float-button"  
      :style="{top: buttonTop + 'px', left: buttonLeft + 'px'}"  
      @touchstart="handleTouchStart"  
      @touchmove="handleTouchMove"  
      @touchend="handleTouchEnd"  
    >  
      <image class="button-icon" src="@/static/icon/add.png" />  
    </view>  
  </view>  
</template>  
  
<script>  
export default {  
  data() {  
    const screenInfo = uni.getSystemInfoSync();  
    const screenWidth = screenInfo.windowWidth;  
    const screenHeight = screenInfo.windowHeight;  
    const buttonSize = 60; // 按钮的宽度和高度  
  
    return {  
      buttonTop: screenHeight - buttonSize - 100, // 30 是距离底部的间距  
      buttonLeft: screenWidth - buttonSize - 50, // 30 是距离右侧的间距  
      startX: 0,  
      startY: 0,  
      isDragging: false  
    };  
  },  
  methods: {  
    handleTouchStart(event) {  
      this.startX = event.touches[0].clientX;  
      this.startY = event.touches[0].clientY;  
      this.isDragging = true;  
    },  
    handleTouchMove(event) {  
      if (this.isDragging) {  
        const touch = event.touches[0];  
        const deltaX = touch.clientX - this.startX;  
        const deltaY = touch.clientY - this.startY;  
  
        let newTop = this.buttonTop + deltaY;  
        let newLeft = this.buttonLeft + deltaX;  
  
        const screenInfo = uni.getSystemInfoSync();  
        const screenWidth = screenInfo.windowWidth;  
        const screenHeight = screenInfo.windowHeight;  
  
        if (newTop < 0) newTop = 0;  
        if (newTop + 60 > screenHeight) newTop = screenHeight - 60;  
        if (newLeft < 0) newLeft = 0;  
        if (newLeft + 60 > screenWidth) newLeft = screenWidth - 60;  
  
        this.buttonTop = newTop;  
        this.buttonLeft = newLeft;  
  
        this.startX = touch.clientX;  
        this.startY = touch.clientY;  
      }  
    },  
    handleTouchEnd() {  
      this.isDragging = false;  
    }  
  }  
};  
</script>  
  
<style scoped>  
.container {  
  position: relative;  
  width: 100%;  
  height: 100vh;  
  overflow: hidden;  
}  
  
.float-button {  
  position: absolute;  
  width: 60px;  
  height: 60px;  
  background: linear-gradient(45deg, #ff6b6b, #f06595);  
  border-radius: 50%;  
  display: flex;  
  justify-content: center;  
  align-items: center;  
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2),  
              0 2px 4px rgba(0, 0, 0, 0.1) inset,  
              0 -1px 1px rgba(255, 255, 255, 0.3) inset;  
  cursor: pointer;  
  user-select: none;  
  touch-action: none;  
}  
  
.button-icon {  
  width: 60%;  
  height: 60%;  
  object-fit: contain;  
}  
</style>

#####发光

<template>
  <view class="container">
    <view class="circle-container">
      <view class="outer-ring"></view>
      <view class="circle-button">  <span class="text">寄</span></view>
    </view>
  </view>
</template>

<script setup>
// 无需额外的逻辑,因为我们将使用纯 CSS 来完成布局和样式
</script>

<style scoped>
.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh; /* 使用视口高度单位 */
  background-color: #f0f0f0;
}

/* 使用绝对定位来实现向上偏移 */
.circle-container {
  position: relative;
  transform: translateY(-25px); /* 调整偏移量 */
}

/* 圆形按钮样式 */
.circle-button {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background: linear-gradient(145deg, #add8e6 0%, #90ee90 100%);
  box-shadow: 0px 5px 10px rgba(0, 255, 255, 0.3);
  transition: all 0.2s ease-in-out;
  display: flex; /* 使用 Flexbox 布局 */
  justify-content: center; /* 水平居中 */
  align-items: center; /* 垂直居中 */
  animation: gradientColorChange 10s ease-in-out infinite;
}

/* 添加文本 */
.text {
  color: white;
  font-size: 40px; /* 字体大小 */
  font-weight: bold; /* 加粗字体 */
  user-select: none; /* 防止用户选择文字 */
}

/* 添加外圈 */
.outer-ring {
  position: absolute;
  top: -15px; /* 减小距离 */
  left: -15px; /* 减小距离 */
  right: -15px; /* 减小距离 */
  bottom: -15px; /* 减小距离 */
  margin: auto;
  border-radius: 50%;
  background: transparent;
  pointer-events: none; /* 确保不会影响点击事件 */
  animation: glow 3s ease-in-out infinite;
  box-shadow: 0px 0px 20px 10px rgba(0, 255, 255, 0.6);
}

/* 定义颜色变化的关键帧 */
@keyframes colorChange {
  0% {
    box-shadow: 0px 0px 20px 10px rgba(144, 238, 144, 0.8); /* 淡绿 */
  }
  20% {
    box-shadow: 0px 0px 20px 10px rgba(173, 216, 230, 0.8); /* 淡蓝 */
  }
  40% {
    box-shadow: 0px 0px 20px 10px rgba(255, 165, 0, 0.8); /* 淡橙 */
  }
  60% {
    box-shadow: 0px 0px 20px 10px rgba(160, 32, 240, 0.8); /* 淡紫 */
  }
  80% {
    box-shadow: 0px 0px 20px 10px rgba(210, 105, 30, 0.8); /* 淡棕 */
  }
  100% {
    box-shadow: 0px 0px 20px 10px rgba(144, 238, 144, 0.8); /* 淡绿 */
  }
}

/* 应用颜色变化动画 */
.outer-ring {
  animation: colorChange 10s ease-in-out infinite;
}
</style>

评论

加载中...