Skip to content
字数
289 字
阅读时间
2 分钟
html
<template>
	<div
		class="floating-button"
		ref="buttonRef"
		:style="{ right: buttonPosition.x + 'px', bottom: buttonPosition.y + 'px' }"
		@touchstart="startDrag"
	>
		<slot><img :src="icon" class="w-50 h-50" alt="" /></slot>
	</div>
</template>

<script setup lang="ts">
	import { ref, onMounted } from "vue";
	import { throttle } from "@/utils/tool";

	const props = withDefaults(
		defineProps<{
			icon?: string;
			positionRight?: number;
			positionBottom?: number;
		}>(),
		{
			icon: "https://img.danchuangglobal.com/resource/images/bdcce849-650b-4bf6-9f44-60825ced7ad5.png?x-oss-process=image/quality,q_80/interlace,1",
			positionRight: 6,
			positionBottom: 70,
		}
	);

	const kfImgUrl =
		"https://img.danchuangglobal.com/resource/images/bdcce849-650b-4bf6-9f44-60825ced7ad5.png?x-oss-process=image/quality,q_80/interlace,1";

	const buttonRef = ref<HTMLElement | null>(null);
	const buttonPosition = ref({ x: 0, y: 0 });
	let offsetX = 0;
	let offsetY = 0;
	const THROTTLE_RATE = 16; // 60fps

	// 节流
	const handleDrag = throttle((event: TouchEvent) => {
		event.preventDefault(); // 阻止默认滚动行为
		const touch = event.touches[0];
		const buttonWidth = buttonRef.value!.offsetWidth;
		const buttonHeight = buttonRef.value!.offsetHeight;
		const newX = window.innerWidth - touch.clientX - offsetX - buttonWidth / 2; // 按钮位置 + 二次手指位置 = 偏移距离
		const newY =
			window.innerHeight - touch.clientY - offsetY - buttonHeight / 2;
		const maxX = window.innerWidth - buttonWidth;
		const maxY = window.innerHeight - buttonHeight;
		buttonPosition.value = {
			x: Math.min(maxX, Math.max(0, newX)),
			y: Math.min(maxY, Math.max(0, newY)),
		};
	}, THROTTLE_RATE);

	const stopDrag = () => {
		document.removeEventListener("touchmove", handleDrag);
		document.removeEventListener("touchend", stopDrag);
	};

	const startDrag = (event: TouchEvent) => {
		event.preventDefault(); // 阻止默认滚动行为
		const touch = event.touches[0];
		const buttonRect = buttonRef.value!.getBoundingClientRect();
		offsetX = touch.clientX - buttonRect.left - buttonRect.width / 2; // 计算初次手指相对按钮偏移位置
		offsetY = touch.clientY - buttonRect.top - buttonRect.height / 2;
		document.addEventListener("touchmove", handleDrag);
		document.addEventListener("touchend", stopDrag);
	};

	onMounted(() => {
		buttonPosition.value = {
			x: props.positionRight!,
			y: props.positionBottom!,
		};
	});
</script>

<style scoped>
	.floating-button {
		position: fixed;
		z-index: 999;
		cursor: pointer;
	}
</style>

贡献者

jiechen

文件历史