231 lines
6.0 KiB
HTML
231 lines
6.0 KiB
HTML
<style>
|
|
.floating-btn {
|
|
position: fixed;
|
|
width: 80px;
|
|
height: 80px;
|
|
background-color: #ffffff;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
cursor: move;
|
|
user-select: none;
|
|
z-index: 1;
|
|
/* z-index: 1000; */
|
|
transition:
|
|
background-color 0.3s,
|
|
left 0.3s ease,
|
|
right 0.3s ease,
|
|
top 0.3s ease;
|
|
}
|
|
|
|
.floating-btn:active {
|
|
cursor: grabbing;
|
|
}
|
|
|
|
|
|
.floating-btn {
|
|
touch-action: none; /* Evita que el navegador maneje los eventos touch */
|
|
}
|
|
|
|
@media (hover: none) {
|
|
.floating-btn {
|
|
cursor: pointer; /* Cambia el cursor en dispositivos táctiles */
|
|
}
|
|
}
|
|
|
|
</style>
|
|
|
|
<div class="floating-btn border border-light shadow-lg" id="floatingBtn">
|
|
<a id="floatingBtnLink" target="_blank" href="https://chatgpt.com/g/g-6828126fba608191a2803ac89f54f504-formha-rh-para-pymes">
|
|
<img src="{{ url_for('static', filename='y_img/logos/chat_ia_formha.svg') }}"
|
|
alt="logo"
|
|
class="img-fluid rounded-circle rotating"
|
|
style="width: 100%; height: 100%;">
|
|
</a>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
const btn = document.getElementById('floatingBtn');
|
|
const link = document.getElementById('floatingBtnLink');
|
|
let offsetX, offsetY;
|
|
let isDragging = false;
|
|
let hasMoved = false;
|
|
let touchStartTimer;
|
|
const tapThreshold = 200; // Tiempo en milisegundos para considerar un "tap"
|
|
const moveThreshold = 10; // Distancia en píxeles para considerar un "move"
|
|
let initialTouchX, initialTouchY;
|
|
|
|
|
|
const savedPosition = localStorage.getItem('floatingBtnPosition');
|
|
if (savedPosition) {
|
|
const { x, y } = JSON.parse(savedPosition);
|
|
btn.style.left = x;
|
|
btn.style.top = y;
|
|
setTimeout(() => stickToNearestSide(parseInt(x), parseInt(y)), 10);
|
|
} else {
|
|
btn.style.right = '20px';
|
|
btn.style.top = '20px';
|
|
}
|
|
|
|
// Eventos para mouse
|
|
btn.addEventListener('mousedown', startDrag);
|
|
document.addEventListener('mousemove', drag);
|
|
document.addEventListener('mouseup', stopDrag);
|
|
|
|
|
|
// Eventos para touch
|
|
btn.addEventListener('touchstart', startTouch, { passive: false });
|
|
btn.addEventListener('touchmove', moveTouch, { passive: false });
|
|
btn.addEventListener('touchend', endTouch);
|
|
|
|
link.addEventListener('click', function (e) {
|
|
if (hasMoved) {
|
|
e.preventDefault();
|
|
hasMoved = false;
|
|
}
|
|
});
|
|
|
|
function startDrag(e) {
|
|
isDragging = true;
|
|
hasMoved = false;
|
|
|
|
const rect = btn.getBoundingClientRect();
|
|
offsetX = e.clientX - rect.left;
|
|
offsetY = e.clientY - rect.top;
|
|
|
|
btn.style.cursor = 'grabbing';
|
|
btn.style.left = `${rect.left}px`;
|
|
btn.style.top = `${rect.top}px`;
|
|
btn.style.right = 'auto';
|
|
|
|
e.preventDefault();
|
|
}
|
|
|
|
function drag(e) {
|
|
if (!isDragging) return;
|
|
|
|
const x = e.clientX - offsetX;
|
|
const y = e.clientY - offsetY;
|
|
|
|
btn.style.left = `${x}px`;
|
|
btn.style.top = `${y}px`;
|
|
|
|
hasMoved = true;
|
|
}
|
|
|
|
function stopDrag() {
|
|
if (!isDragging) return;
|
|
|
|
isDragging = false;
|
|
btn.style.cursor = 'move';
|
|
|
|
const rect = btn.getBoundingClientRect();
|
|
const x = rect.left;
|
|
const y = rect.top;
|
|
|
|
stickToNearestSide(x, y);
|
|
savePosition(x, y);
|
|
}
|
|
|
|
|
|
function startTouch(e) {
|
|
if (e.touches.length !== 1) return;
|
|
|
|
e.preventDefault(); // Prevenir comportamiento por defecto
|
|
const touch = e.touches[0];
|
|
initialTouchX = touch.clientX;
|
|
initialTouchY = touch.clientY;
|
|
|
|
const rect = btn.getBoundingClientRect();
|
|
offsetX = initialTouchX - rect.left;
|
|
offsetY = initialTouchY - rect.top;
|
|
|
|
hasMoved = false;
|
|
touchStartTimer = setTimeout(() => {
|
|
if (!isDragging) {
|
|
link.click();
|
|
}
|
|
}, tapThreshold);
|
|
}
|
|
|
|
|
|
|
|
function moveTouch(e) {
|
|
if (!touchStartTimer || e.touches.length !== 1 || !initialTouchX) return;
|
|
|
|
const touch = e.touches[0];
|
|
const currentX = touch.clientX;
|
|
const currentY = touch.clientY;
|
|
|
|
// Verificar si el movimiento supera el umbral
|
|
if (Math.abs(currentX - initialTouchX) > moveThreshold ||
|
|
Math.abs(currentY - initialTouchY) > moveThreshold) {
|
|
clearTimeout(touchStartTimer);
|
|
isDragging = true;
|
|
hasMoved = true;
|
|
|
|
btn.style.cursor = 'grabbing';
|
|
btn.style.left = `${currentX - offsetX}px`;
|
|
btn.style.top = `${currentY - offsetY}px`;
|
|
btn.style.right = 'auto';
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function endTouch(e) {
|
|
clearTimeout(touchStartTimer);
|
|
if (isDragging) {
|
|
isDragging = false;
|
|
btn.style.cursor = 'move';
|
|
const rect = btn.getBoundingClientRect();
|
|
stickToNearestSide(rect.left, rect.top);
|
|
savePosition(rect.left, rect.top);
|
|
}
|
|
initialTouchX = null;
|
|
initialTouchY = null;
|
|
}
|
|
|
|
function stickToNearestSide(x, y) {
|
|
const windowWidth = window.innerWidth;
|
|
const btnWidth = btn.offsetWidth;
|
|
|
|
if (x < windowWidth / 2) {
|
|
btn.style.left = '10px';
|
|
btn.style.right = 'auto';
|
|
} else {
|
|
btn.style.left = 'auto';
|
|
btn.style.right = '10px';
|
|
}
|
|
|
|
const windowHeight = window.innerHeight;
|
|
const btnHeight = btn.offsetHeight;
|
|
|
|
if (y < 0) {
|
|
btn.style.top = '10px';
|
|
} else if (y + btnHeight > windowHeight) {
|
|
btn.style.top = `${windowHeight - btnHeight - 10}px`;
|
|
} else {
|
|
btn.style.top = `${y}px`;
|
|
}
|
|
}
|
|
|
|
function savePosition(x, y) {
|
|
localStorage.setItem('floatingBtnPosition', JSON.stringify({
|
|
x: btn.style.left,
|
|
y: btn.style.top
|
|
}));
|
|
}
|
|
|
|
window.addEventListener('resize', function () {
|
|
const savedPosition = localStorage.getItem('floatingBtnPosition');
|
|
if (savedPosition) {
|
|
const { x, y } = JSON.parse(savedPosition);
|
|
stickToNearestSide(parseInt(x), parseInt(y));
|
|
}
|
|
});
|
|
});
|
|
</script> |