第一个是组件 第二个是直接在页面 第三个是发光按钮
#####是组件
<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>

评论