Chú giải công cụ từ tính là một thành phần giao diện người dùng phong phú, di chuyển mượt mà theo con trỏ của người dùng.
requestAnimationFrame đạt được chuyển động mượt mà mà không bị giật hình.box-shadow và backdrop-filter, chúng tôi tạo ra hiệu ứng ba chiều như thể các phần tử đang nổi trên màn hình.pointer-events: none để không can thiệp vào thao tác di chuột của người dùng.const speed = 0,15; trong JavaScript (gần 1, nhanh hơn).tuyến tính-gradient và .magnetic-tooltip của .magnetic-target trong CSS để phù hợp với chủ đề dự án.transform: ... TranslateY(-15px); trong .magnetic-tooltip.visible.<div class="magnetic-tooltip-container">
<button class="magnetic-target" data-tooltip="🚀 新しいアップデートが利用可能です">
Hover Me
</button>
<button class="magnetic-target" data-tooltip="✨ プレミアム機能を見る">
Explore
</button>
<div class="magnetic-tooltip"></div>
</div>
<style>
.magnetic-tooltip-container {
display: flex;
gap: 2rem;
justify-content: center;
align-items: center;
min-height: 400px;
background: #000000;
background-image: radial-gradient(circle at 50% 50%, #1a1a2e 0%, #000000 100%);
border-radius: 1rem;
position: relative;
font-family: 'Inter', system-ui, sans-serif;
}
.magnetic-target {
padding: 1rem 2.5rem;
font-size: 1.125rem;
font-weight: 600;
color: #ffffff;
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 9999px;
cursor: pointer;
box-shadow: 0 10px 30px -10px rgba(139, 92, 246, 0.5);
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.3s ease, filter 0.3s ease;
}
.magnetic-target:hover {
box-shadow: 0 20px 40px -10px rgba(139, 92, 246, 0.7);
filter: brightness(1.1);
}
.magnetic-tooltip {
position: fixed;
top: 0;
left: 0;
pointer-events: none;
padding: 0.75rem 1.25rem;
background: rgba(15, 23, 42, 0.85);
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 0.75rem;
color: #f8fafc;
font-size: 0.875rem;
font-weight: 500;
white-space: nowrap;
box-shadow:
0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 24px 38px 3px rgba(0, 0, 0, 0.14),
inset 0 1px 0 rgba(255, 255, 255, 0.1);
opacity: 0;
transform: translate(-50%, -100%) scale(0.9) translateY(10px);
transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
z-index: 9999;
}
.magnetic-tooltip.visible {
opacity: 1;
transform: translate(-50%, -100%) scale(1) translateY(-15px);
}
</style>
<script>
(function initMagneticTooltip() {
const targets = document.querySelectorAll('.magnetic-target');
const tooltip = document.querySelector('.magnetic-tooltip');
if(!tooltip) return;
let mouseX = 0;
let mouseY = 0;
let tooltipX = 0;
let tooltipY = 0;
let isHovered = false;
let animationFrameId;
const speed = 0.15;
function animate() {
if (isHovered) {
tooltipX += (mouseX - tooltipX) * speed;
tooltipY += (mouseY - tooltipY) * speed;
tooltip.style.left = tooltipX + 'px';
tooltip.style.top = tooltipY + 'px';
animationFrameId = requestAnimationFrame(animate);
}
}
targets.forEach(function(target) {
target.addEventListener('mouseenter', function(e) {
isHovered = true;
tooltip.textContent = target.getAttribute('data-tooltip');
tooltip.classList.add('visible');
mouseX = e.clientX;
mouseY = e.clientY;
tooltipX = mouseX;
tooltipY = mouseY;
tooltip.style.left = tooltipX + 'px';
tooltip.style.top = tooltipY + 'px';
if (animationFrameId) cancelAnimationFrame(animationFrameId);
animate();
});
target.addEventListener('mousemove', function(e) {
mouseX = e.clientX;
mouseY = e.clientY;
// Magnetic pull effect on the button itself
const rect = target.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const deltaX = (mouseX - centerX) * 0.3;
const deltaY = (mouseY - centerY) * 0.3;
target.style.transform = 'translate(' + deltaX + 'px, ' + deltaY + 'px) scale(1.05)';
});
target.addEventListener('mouseleave', function() {
isHovered = false;
tooltip.classList.remove('visible');
target.style.transform = ''; // reset button position
if (animationFrameId) cancelAnimationFrame(animationFrameId);
});
});
})();
</script> *Thuộc tính backdrop-filter được hỗ trợ bởi các trình duyệt chính mới nhất. Safari sử dụng tiền tố -webkit-.