0
0
Lập trình
Flame Kris
Flame Krisbacodekiller

Xây Dựng Huy Hiệu 3D Tương Tác Bằng HTML, CSS và JavaScript

Đăng vào 1 tuần trước

• 5 phút đọc

🎯 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 Copy
<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 Copy
<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 Copy
<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 Copy
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 Copy
.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 Copy
.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 Copy
@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 Copy
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! 🚀

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào