otro intento btn flotante
This commit is contained in:
parent
b15b7093b1
commit
1e2631d32e
@ -39,47 +39,110 @@
|
|||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
const btn = document.getElementById('floatingBtn');
|
const btn = document.getElementById('floatingBtn');
|
||||||
const link = document.getElementById('floatingBtnLink');
|
const link = document.getElementById('floatingBtnLink');
|
||||||
let offsetX, offsetY; // Desplazamiento del puntero/dedo dentro del botón
|
let offsetX, offsetY;
|
||||||
let isDragging = false; // Estado de arrastre
|
let isDragging = false;
|
||||||
let hasMoved = false; // Indica si el botón se ha movido lo suficiente para ser considerado arrastre
|
let hasMoved = false;
|
||||||
let startClientX, startClientY; // Coordenadas iniciales del toque/clic
|
let startClientX, startClientY;
|
||||||
const moveThreshold = 5; // Distancia en píxeles para considerar un "move"
|
const moveThreshold = 10; // Aumenté el umbral para mejor experiencia táctil
|
||||||
|
let tapTimer;
|
||||||
|
|
||||||
// --- Cargar y aplicar la posición guardada ---
|
// Cargar posición guardada
|
||||||
const savedPosition = localStorage.getItem('floatingBtnPosition');
|
const savedPosition = localStorage.getItem('floatingBtnPosition');
|
||||||
if (savedPosition) {
|
if (savedPosition) {
|
||||||
const { x, y } = JSON.parse(savedPosition);
|
const { x, y } = JSON.parse(savedPosition);
|
||||||
btn.style.left = x;
|
btn.style.left = x;
|
||||||
btn.style.top = y;
|
btn.style.top = y;
|
||||||
// Usamos requestAnimationFrame para asegurar que la posición se aplique después del renderizado.
|
|
||||||
// Esto evita posibles glitches al inicio.
|
|
||||||
requestAnimationFrame(() => stickToNearestSide(parseInt(x), parseInt(y)));
|
requestAnimationFrame(() => stickToNearestSide(parseInt(x), parseInt(y)));
|
||||||
} else {
|
} else {
|
||||||
// Posición inicial por defecto si no hay nada guardado
|
|
||||||
btn.style.right = '20px';
|
btn.style.right = '20px';
|
||||||
btn.style.top = '20px';
|
btn.style.top = '20px';
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Eventos para mouse (click y arrastre) ---
|
// Eventos para mouse
|
||||||
btn.addEventListener('mousedown', startInteraction);
|
btn.addEventListener('mousedown', startInteraction);
|
||||||
document.addEventListener('mousemove', moveInteraction);
|
document.addEventListener('mousemove', moveInteraction);
|
||||||
document.addEventListener('mouseup', endInteraction);
|
document.addEventListener('mouseup', endInteraction);
|
||||||
|
|
||||||
// --- Eventos para touch (tap y arrastre) ---
|
// Eventos para touch
|
||||||
// passive: false es CRUCIAL para poder usar e.preventDefault() en touchmove y evitar el scroll no deseado.
|
btn.addEventListener('touchstart', handleTouchStart, { passive: false });
|
||||||
btn.addEventListener('touchstart', startInteraction, { passive: false });
|
btn.addEventListener('touchend', handleTouchEnd, { passive: false });
|
||||||
document.addEventListener('touchmove', moveInteraction, { passive: false });
|
document.addEventListener('touchmove', handleTouchMove, { passive: false });
|
||||||
document.addEventListener('touchend', endInteraction);
|
|
||||||
|
|
||||||
// --- Evitar que el enlace se abra si se ha arrastrado el botón ---
|
// Manejar el clic/enlace
|
||||||
link.addEventListener('click', function (e) {
|
link.addEventListener('click', handleLinkClick);
|
||||||
if (hasMoved) {
|
|
||||||
e.preventDefault(); // Si se movió, previene el click
|
function handleTouchStart(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const touch = e.touches[0];
|
||||||
|
startClientX = touch.clientX;
|
||||||
|
startClientY = touch.clientY;
|
||||||
|
|
||||||
|
const rect = btn.getBoundingClientRect();
|
||||||
|
offsetX = startClientX - rect.left;
|
||||||
|
offsetY = startClientY - rect.top;
|
||||||
|
|
||||||
|
isDragging = false;
|
||||||
|
hasMoved = false;
|
||||||
|
|
||||||
|
// Iniciar temporizador para el tap
|
||||||
|
tapTimer = setTimeout(() => {
|
||||||
|
if (!isDragging) {
|
||||||
|
simulateClick(link);
|
||||||
|
}
|
||||||
|
}, 300); // 300ms es el tiempo típico para considerar un tap
|
||||||
}
|
}
|
||||||
hasMoved = false; // Resetear para la siguiente interacción
|
|
||||||
});
|
|
||||||
|
|
||||||
// --- Función para iniciar la interacción (mousedown o touchstart) ---
|
function handleTouchMove(e) {
|
||||||
|
if (!startClientX) return;
|
||||||
|
|
||||||
|
const touch = e.touches[0];
|
||||||
|
const currentX = touch.clientX;
|
||||||
|
const currentY = touch.clientY;
|
||||||
|
|
||||||
|
const deltaX = Math.abs(currentX - startClientX);
|
||||||
|
const deltaY = Math.abs(currentY - startClientY);
|
||||||
|
|
||||||
|
if (deltaX > moveThreshold || deltaY > moveThreshold) {
|
||||||
|
clearTimeout(tapTimer);
|
||||||
|
isDragging = true;
|
||||||
|
hasMoved = true;
|
||||||
|
|
||||||
|
btn.style.left = `${currentX - offsetX}px`;
|
||||||
|
btn.style.top = `${currentY - offsetY}px`;
|
||||||
|
btn.style.right = 'auto';
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTouchEnd(e) {
|
||||||
|
clearTimeout(tapTimer);
|
||||||
|
if (isDragging) {
|
||||||
|
isDragging = false;
|
||||||
|
const rect = btn.getBoundingClientRect();
|
||||||
|
stickToNearestSide(rect.left, rect.top);
|
||||||
|
savePosition(rect.left, rect.top);
|
||||||
|
}
|
||||||
|
startClientX = null;
|
||||||
|
startClientY = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function simulateClick(element) {
|
||||||
|
const clickEvent = new MouseEvent('click', {
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
view: window
|
||||||
|
});
|
||||||
|
element.dispatchEvent(clickEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleLinkClick(e) {
|
||||||
|
if (hasMoved) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
hasMoved = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funciones restantes igual que antes...
|
||||||
function startInteraction(e) {
|
function startInteraction(e) {
|
||||||
// Prevenir el comportamiento por defecto del navegador (ej. arrastrar imágenes)
|
// Prevenir el comportamiento por defecto del navegador (ej. arrastrar imágenes)
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -108,7 +171,6 @@
|
|||||||
btn.style.cursor = 'grabbing'; // Cambiar cursor mientras se "agarra"
|
btn.style.cursor = 'grabbing'; // Cambiar cursor mientras se "agarra"
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Función para mover (mousemove o touchmove) ---
|
|
||||||
function moveInteraction(e) {
|
function moveInteraction(e) {
|
||||||
if (!startClientX) return; // Si no hay inicio de interacción, salimos
|
if (!startClientX) return; // Si no hay inicio de interacción, salimos
|
||||||
|
|
||||||
@ -136,7 +198,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Función para finalizar la interacción (mouseup o touchend) ---
|
|
||||||
function endInteraction() {
|
function endInteraction() {
|
||||||
// Resetear las coordenadas iniciales del toque
|
// Resetear las coordenadas iniciales del toque
|
||||||
startClientX = null;
|
startClientX = null;
|
||||||
@ -153,7 +214,7 @@
|
|||||||
// hasMoved se reseteará en el evento 'click' del enlace o en la siguiente 'startInteraction'
|
// hasMoved se reseteará en el evento 'click' del enlace o en la siguiente 'startInteraction'
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Función para anclar el botón al lado más cercano ---
|
|
||||||
function stickToNearestSide(x, y) {
|
function stickToNearestSide(x, y) {
|
||||||
const windowWidth = window.innerWidth;
|
const windowWidth = window.innerWidth;
|
||||||
const windowHeight = window.innerHeight;
|
const windowHeight = window.innerHeight;
|
||||||
@ -180,7 +241,6 @@
|
|||||||
btn.style.top = `${newY}px`;
|
btn.style.top = `${newY}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Función para guardar la posición en localStorage ---
|
|
||||||
function savePosition(x, y) {
|
function savePosition(x, y) {
|
||||||
localStorage.setItem('floatingBtnPosition', JSON.stringify({
|
localStorage.setItem('floatingBtnPosition', JSON.stringify({
|
||||||
x: btn.style.left,
|
x: btn.style.left,
|
||||||
@ -188,7 +248,6 @@
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Ajustar posición al redimensionar la ventana ---
|
|
||||||
window.addEventListener('resize', function () {
|
window.addEventListener('resize', function () {
|
||||||
const saved = localStorage.getItem('floatingBtnPosition');
|
const saved = localStorage.getItem('floatingBtnPosition');
|
||||||
if (saved) {
|
if (saved) {
|
||||||
@ -200,5 +259,6 @@
|
|||||||
stickToNearestSide(btn.getBoundingClientRect().left, btn.getBoundingClientRect().top);
|
stickToNearestSide(btn.getBoundingClientRect().left, btn.getBoundingClientRect().top);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
});
|
||||||
</script>
|
</script>
|
Loading…
x
Reference in New Issue
Block a user