下载按钮可拖动
This commit is contained in:
@@ -1,20 +1,131 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
import { useDownload } from '@/contexts/DownloadContext';
|
||||
|
||||
export function DownloadBubble() {
|
||||
const { tasks, downloadingCount, setShowDownloadPanel } = useDownload();
|
||||
|
||||
// 拖动状态
|
||||
const [position, setPosition] = useState({ x: 0, y: 0 });
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
|
||||
|
||||
// 初始化位置(右下角)
|
||||
useEffect(() => {
|
||||
const initPosition = () => {
|
||||
setPosition({
|
||||
x: window.innerWidth - 80,
|
||||
y: window.innerHeight - 80
|
||||
});
|
||||
};
|
||||
|
||||
initPosition();
|
||||
window.addEventListener('resize', initPosition);
|
||||
return () => window.removeEventListener('resize', initPosition);
|
||||
}, []);
|
||||
|
||||
// 处理拖动
|
||||
useEffect(() => {
|
||||
const handleMouseMove = (e: MouseEvent) => {
|
||||
if (!isDragging) return;
|
||||
|
||||
const newX = e.clientX - dragOffset.x;
|
||||
const newY = e.clientY - dragOffset.y;
|
||||
|
||||
// 限制在视口范围内
|
||||
const maxX = window.innerWidth - 64;
|
||||
const maxY = window.innerHeight - 64;
|
||||
|
||||
setPosition({
|
||||
x: Math.max(0, Math.min(newX, maxX)),
|
||||
y: Math.max(0, Math.min(newY, maxY))
|
||||
});
|
||||
};
|
||||
|
||||
const handleTouchMove = (e: TouchEvent) => {
|
||||
if (!isDragging) return;
|
||||
e.preventDefault();
|
||||
|
||||
const touch = e.touches[0];
|
||||
const newX = touch.clientX - dragOffset.x;
|
||||
const newY = touch.clientY - dragOffset.y;
|
||||
|
||||
// 限制在视口范围内
|
||||
const maxX = window.innerWidth - 64;
|
||||
const maxY = window.innerHeight - 64;
|
||||
|
||||
setPosition({
|
||||
x: Math.max(0, Math.min(newX, maxX)),
|
||||
y: Math.max(0, Math.min(newY, maxY))
|
||||
});
|
||||
};
|
||||
|
||||
const handleEnd = () => {
|
||||
setIsDragging(false);
|
||||
};
|
||||
|
||||
if (isDragging) {
|
||||
document.addEventListener('mousemove', handleMouseMove);
|
||||
document.addEventListener('mouseup', handleEnd);
|
||||
document.addEventListener('touchmove', handleTouchMove, { passive: false });
|
||||
document.addEventListener('touchend', handleEnd);
|
||||
}
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mousemove', handleMouseMove);
|
||||
document.removeEventListener('mouseup', handleEnd);
|
||||
document.removeEventListener('touchmove', handleTouchMove);
|
||||
document.removeEventListener('touchend', handleEnd);
|
||||
};
|
||||
}, [isDragging, dragOffset]);
|
||||
|
||||
const handleMouseDown = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
if (e.button !== 0) return;
|
||||
setIsDragging(true);
|
||||
const rect = e.currentTarget.getBoundingClientRect();
|
||||
setDragOffset({
|
||||
x: e.clientX - rect.left,
|
||||
y: e.clientY - rect.top
|
||||
});
|
||||
};
|
||||
|
||||
const handleTouchStart = (e: React.TouchEvent<HTMLButtonElement>) => {
|
||||
setIsDragging(true);
|
||||
const touch = e.touches[0];
|
||||
const rect = e.currentTarget.getBoundingClientRect();
|
||||
setDragOffset({
|
||||
x: touch.clientX - rect.left,
|
||||
y: touch.clientY - rect.top
|
||||
});
|
||||
};
|
||||
|
||||
if (tasks.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='fixed bottom-6 right-6 z-[9998]'>
|
||||
<div
|
||||
style={{
|
||||
position: 'fixed',
|
||||
left: `${position.x}px`,
|
||||
top: `${position.y}px`,
|
||||
zIndex: 9998,
|
||||
}}
|
||||
>
|
||||
<button
|
||||
onClick={() => setShowDownloadPanel(true)}
|
||||
onMouseDown={handleMouseDown}
|
||||
onTouchStart={handleTouchStart}
|
||||
onClick={(e) => {
|
||||
if (!isDragging) {
|
||||
setShowDownloadPanel(true);
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
cursor: isDragging ? 'grabbing' : 'grab',
|
||||
touchAction: 'none',
|
||||
}}
|
||||
className='relative group bg-gradient-to-r from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 text-white rounded-full p-4 shadow-lg hover:shadow-xl transition-all duration-300 transform hover:scale-110'
|
||||
>
|
||||
{/* 下载图标 */}
|
||||
|
||||
Reference in New Issue
Block a user