🎯 Những Gì Chúng Ta Sẽ Xây Dựng
- Một huy hiệu hình tròn với viền vàng.
- Chữ cong và ngôi sao xung quanh viền.
- Một trung tâm nổi với số và nhãn động.
- Những hạt lấp lánh bay lơ lửng bên trong.
- Nghiêng 3D khi di chuột.
- Hiệu ứng sóng khi nhấp chuột.
- Các hoạt ảnh và gradient mượt mà.
Hãy cùng tìm hiểu cách thực hiện từng bước.
🏗️ Bước 1: Cấu Trúc HTML
Chúng ta sẽ bắt đầu với một container và xây dựng các lớp bên trong nó.
html
<div class="badge-container">
<div class="coin-edge"></div>
<svg class="badge-svg" viewBox="0 0 200 200">
<!-- Viền ngoài và gradient -->
<circle cx="100" cy="100" r="95" class="outer-circle" />
<circle cx="100" cy="100" r="85" class="inner-circle" />
<!-- Các đường dẫn cho chữ cong -->
<defs>
<path id="circle-top" d="M20,100a80,80 0 1,1 160,0a80,80 0 1,1 -160,0" />
<path id="circle-bottom" d="M180,100a80,80 0 1,1 -160,0a80,80 0 1,1 160,0" />
</defs>
<text class="curved-text">
<textPath href="#circle-top" startOffset="50%" text-anchor="middle">
20 NĂM ORLANDO & CÁC THÀNH PHỐ XUNG QUANH
</textPath>
</text>
<text class="curved-stars">
<textPath href="#circle-bottom" startOffset="50%" text-anchor="middle">
★★★★★
</textPath>
</text>
</svg>
<div class="inner-content-wrapper">
<div class="content2">
<span class="click-effect"></span>
<div class="twenty">20</div>
<div class="years">NĂM</div>
<div class="location">ORLANDO & CÁC THÀNH PHỐ XUNG QUANH</div>
</div>
</div>
<div class="particles"></div>
</div>
Điều này sẽ tạo ra:
.coin-edge
: viền nền.<svg>
: cho các hình tròn viền + chữ cong..inner-content-wrapper
: trung tâm nổi với văn bản..particles
: container cho các yếu tố lấp lánh.
✨ Bước 2: Cách Chữ Cong Hoạt Động
Một trong những đặc điểm hình ảnh chính là chữ cong xung quanh huy hiệu. Điều này được thực hiện bằng cách sử dụng các phần tử SVG <textPath>
gắn văn bản vào một đường tròn <path>
.
1. Định Nghĩa Các Đường Dẫn
Trong phần <defs>
, chúng ta định nghĩa các đường dẫn hình tròn vô hình:
html
<defs>
<path id="circle-top" d="M20,100a80,80 0 1,1 160,0a80,80 0 1,1 -160,0" />
<path id="circle-bottom" d="M180,100a80,80 0 1,1 -160,0a80,80 0 1,1 160,0" />
</defs>
Những đường dẫn này mô tả hai cung:
circle-top
: cong văn bản theo nửa trên.circle-bottom
: cong văn bản theo nửa dưới.
2. Gắn Văn Bản Với <textPath>
html
<text class="curved-text">
<textPath href="#circle-top" startOffset="50%" text-anchor="middle">
20 NĂM ORLANDO & CÁC THÀNH PHỐ XUNG QUANH
</textPath>
</text>
href="#circle-top"
: gắn văn bản vào đường dẫn trên.startOffset="50%"
: căn giữa văn bản theo chiều ngang.text-anchor="middle"
: đảm bảo căn chỉnh văn bản cân bằng.
Tương tự, các ngôi sao ở dưới sử dụng đường dẫn circle-bottom
.
3. Điều Chỉnh Độ Dài Với JavaScript (Tùy Chọn)
Nếu bạn muốn văn bản vừa vặn hoàn toàn theo cung, bạn có thể sử dụng JavaScript để đo độ dài đường dẫn và đặt textLength
một cách động:
javascript
function fitTextToArc(textElement, pathId) {
const path = document.querySelector(pathId);
const pathLength = path.getTotalLength();
textElement.setAttribute('textLength', pathLength);
textElement.setAttribute('lengthAdjust', 'spacing');
}
fitTextToArc(document.querySelector('.curved-text textPath'), '#circle-top');
fitTextToArc(document.querySelector('.curved-stars textPath'), '#circle-bottom');
Điều này đảm bảo văn bản được kéo dài đồng đều trên cung.
🎨 Bước 3: Phong Cách CSS & Hoạt Hình
Cấu Trúc Cơ Bản
css
.badge-container {
position: relative;
width: 300px;
height: 300px;
perspective: 1000px;
animation: badgePulse 4s infinite;
}
.coin-edge {
position: absolute;
inset: 0;
border-radius: 50%;
background: radial-gradient(circle, #ffcc33, #b8860b);
box-shadow: inset 0 0 20px rgba(0,0,0,0.4);
}
.badge-svg {
position: relative;
width: 100%;
height: 100%;
z-index: 2;
}
.outer-circle {
fill: none;
stroke: #ffd700;
stroke-width: 6;
}
.inner-circle {
fill: url(#badgeGradient);
}
Nội Dung Trung Tâm
css
.inner-content-wrapper {
position: absolute;
top: 50%;
left: 50%;
width: 60%;
height: 60%;
border-radius: 50%;
background: radial-gradient(circle, #fff, #f5f5f5);
transform: translate(-50%, -50%) translateZ(40px);
box-shadow: 0 8px 15px rgba(0,0,0,0.4);
}
.content2 {
text-align: center;
position: relative;
padding: 20px;
}
.twenty {
font-size: 3rem;
font-weight: bold;
color: #d4af37;
}
.years {
font-size: 1.5rem;
margin-top: -10px;
color: #333;
}
.location {
font-size: 0.9rem;
color: #666;
}
Hoạt Hình
css
@keyframes badgePulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.02); }
}
.particle {
position: absolute;
width: 5px;
height: 5px;
background: white;
border-radius: 50%;
opacity: 0;
animation: sparkle 5s infinite;
}
@keyframes sparkle {
0% { transform: translateY(0); opacity: 0; }
50% { opacity: 1; }
100% { transform: translateY(-50px); opacity: 0; }
}
.click-effect {
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: rgba(255,215,0,0.5);
border-radius: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
}
.click-effect.active {
animation: ripple 0.6s ease-out;
}
@keyframes ripple {
from { width: 0; height: 0; opacity: 0.8; }
to { width: 200px; height: 200px; opacity: 0; }
}
⚙️ Bước 4: Tương Tác JavaScript
Chúng ta sẽ thêm:
- hoạt ảnh đếm lên,
- tạo ra các hạt,
- hiệu ứng nghiêng,
- sóng khi nhấp chuột.
javascript
document.addEventListener('DOMContentLoaded', () => {
const badge = document.querySelector('.badge-container');
const badge3d = document.createElement('div');
badge3d.classList.add('badge-3d');
while (badge.firstChild) badge3d.appendChild(badge.firstChild);
badge.appendChild(badge3d);
// Tạo hạt
const particles = badge.querySelector('.particles');
for (let i = 0; i < 20; i++) {
const p = document.createElement('div');
p.classList.add('particle');
p.style.left = `${Math.random() * 100}%`;
p.style.top = `${Math.random() * 100}%`;
p.style.animationDelay = `${Math.random() * 5}s`;
particles.appendChild(p);
}
// Đếm lên
const num = document.querySelector('.twenty');
let count = 1;
const target = 20;
const interval = setInterval(() => {
num.textContent = count;
if (count >= target) clearInterval(interval);
count++;
}, 75);
// Hiệu ứng nghiêng
badge.addEventListener('mousemove', (e) => {
const rect = badge.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width - 0.5;
const y = (e.clientY - rect.top) / rect.height - 0.5;
badge3d.style.transform = `rotateX(${y * 20}deg) rotateY(${x * -20}deg)`;
});
badge.addEventListener('mouseleave', () => {
badge3d.style.transform = 'rotateX(0) rotateY(0)';
});
// Sóng khi nhấp chuột
badge.addEventListener('click', () => {
const ripple = document.querySelector('.click-effect');
ripple.classList.remove('active');
void ripple.offsetWidth; // reflow
ripple.classList.add('active');
});
});
✅ Kết Luận
Chỉ với HTML, CSS và JavaScript thuần, chúng ta đã tạo ra một huy hiệu tương tác bóng bẩy mà:
- nghiêng trong không gian 3D,
- lấp lánh với các hạt,
- hoạt hình số đếm lên,
- nhấp nhô sống động,
- có chữ cong theo các cung,
- và phản hồi khi nhấp chuột.
Kỹ thuật tương tự có thể được áp dụng cho:
- Huy hiệu thành tích,
- Token chương trình khách hàng thân thiết,
- Logo kỷ niệm sự kiện,
- Các phần tử giao diện gamification.
Hãy thử nghiệm, tùy chỉnh màu sắc và văn bản, và biến nó thành của bạn! 🚀