Bootstrap

uniapp封装movable-area+movable-view组件,实现悬浮按钮可拖动,自动吸附边缘效果,自动向两边靠拢

兼容H5、App、微信小程序

子组件

/components/ShopCar/ShopCar.vue

<template>
	<view class="ShopCar">
		<movable-area class="movableArea" v-if="isShow">
			<movable-view class="movableView" :position="position" :x="x" :y="y" :direction="direction"
				:damping="damping" @change="onChange" @touchend="onTouchend">
				<view class="icon-box" @click="handleIcon()">
					<u-icon name="arrow-upward" color="#ff6a00" size="20"></u-icon>
				</view>
			</movable-view>
		</movable-area>
	</view>
</template>

<script>
	export default {
		props: {
			damping: {
				type: Number,
				default: 10
			},
			direction: {
				type: String,
				default: "all"
			},
			position: {
				type: Number,
				default: 4
			},
		},
		data() {
			return {
				x: 0,
				y: 0,
				x1: 0,
				x2: 0,
				y1: 0,
				y2: 0,
				move: {
					x: 0,
					y: 0
				},
				isShow: false
			}
		},
		mounted() {
			uni.getSystemInfo({
				success: (res) => {
					this.x1 = 0;
					this.x2 = parseInt(res.windowWidth) - 50;
					this.y1 = 0;
					this.y2 = parseInt(res.windowHeight) - 20;
					this.$nextTick(() => {
						if (this.position == 1 || this.position == 2) this.y = parseInt(this.y2 * 0.2);
						if (this.position == 3 || this.position == 4) this.y = parseInt(this.y2 * 0.8);
						if (this.position == 1 || this.position == 3) this.x = parseInt(this.x1);
						if (this.position == 2 || this.position == 4) this.x = parseInt(this.x2);
						this.move.x = this.x;
						this.move.y = this.y;
						this.isShow = true
					})
				}
			})
		},

		methods: {
			onChange(e) {
				if (e.detail.source === "touch") {
					this.move.x = e.detail.x;
					this.move.y = e.detail.y;
				}
			},
			onTouchend() {
				this.x = this.move.x;
				this.y = this.move.y;
				this.$nextTick(() => {
					if (this.move.x < this.x2 / 2) this.x = this.x1;
					else this.x = this.x2;
				})
			},
			handleIcon() {
				uni.pageScrollTo({
					scrollTop: 0,
					duration: 0,
				});
			}
		},
	}
</script>

<style lang="scss" scoped>
	.ShopCar {
		.movableArea {
			position: fixed;
			top: 0;
			left: 0;
			width: 100%;
			height: 100%;
			pointer-events: none; //设置area元素不可点击,则事件便会下移至页面下层元素
			z-index: 999;

			.movableView {
				width: 70rpx;
				height: 70rpx;
				pointer-events: auto;
				padding: 0 30rpx;

				.icon-box {
					width: 100%;
					height: 100%;
					display: flex;
					align-items: center;
					justify-content: center;
					border: 1rpx solid #ff6a00;
					box-sizing: border-box;
					border-radius: 50%;
					background-color: #fff;
					animation: iconBox 5s linear infinite; //进行旋转
				}

				@keyframes iconBox {
					0% {
						-webkit-transform: rotate(0deg);
					}

					25% {
						-webkit-transform: rotate(90deg);
					}

					50% {
						-webkit-transform: rotate(180deg);
					}

					75% {
						-webkit-transform: rotate(270deg);
					}

					100% {
						-webkit-transform: rotate(360deg);
					}
				}

			}
		}
	}
</style>

父组件

<template>
   <ShopCar v-if="scrollTop>200" />
</template>

<script>
	export default {
		data() {
            return {
                scrollTop: 0
            }
        },
        onPageScroll(e) {
		    this.scrollTop = e.scrollTop
        },
    }
</script>

;