← Tất cả bài viết

[ Blog ]

27 tháng 6, 2026

10 phút đọc

Mathijs Hanenkamp: Case Study Website Nhiếp Ảnh

Case study website portfolio nhiếp ảnh — cách kết hợp WordPress, GSAP và WebGL thành một trải nghiệm lấy hình ảnh làm trọng tâm, đoạt Awwwards Honorable Mention.

Case StudyAwwwardsWordPressGSAPThree.jsWebGLNhiếp Ảnh
Mathijs Hanenkamp: Case Study Website Nhiếp Ảnh

Khi sản phẩm chính là con mắt của một nhiếp ảnh gia, website chỉ có một nhiệm vụ: lùi lại phía sau và làm cho tác phẩm trở nên đắt giá hơn. Case study Mathijs Hanenkamp này phân tích cách tôi dựng một website portfolio nhiếp ảnh làm đúng điều đó — một trải nghiệm lấy hình ảnh làm trọng tâm, dệt từ WordPress, GSAP và WebGL, đoạt Awwwards Honorable Mention. Mathijs là nhiếp ảnh gia chân dung và tư liệu ở Nijmegen, Hà Lan, và đề bài tưởng đơn giản: dựng một thứ tôn được ảnh lên mà không bao giờ tranh chấp với nó. Đây là phần craft phía sau, viết bởi chính người đã ship nó.

Ai làm — và vì sao vai trò developer quan trọng

Site Mathijs Hanenkamp là sự hợp tác giữa designer Huy Phan — một thành viên ban giám khảo Awwwards — và Hon Tran ở vai trò creative developer. Đó là tôi.

Tôi nói ra điều này vì một lý do cụ thể. Portfolio nhiếp ảnh là loại site khó thêm chuyển động nhất, vì mỗi hiệu ứng đều có nguy cơ gây hại: một transition nặng làm mềm ảnh, một animation cuộn làm phân tâm khỏi bố cục, một hover "thông minh" kéo mắt khỏi gương mặt trong khung hình. Điều kiện thắng không phải là "thêm animation" — mà là chuyển động khiến bức ảnh hiện diện rõ hơn. Tôi đã có hơn 11 năm dựng các trải nghiệm web đoạt giải cho khách hàng ở Na Uy, Đan Mạch, Thụy Điển, Malta, Đức và Việt Nam; từng hai lần được Awwwards vinh danh "Independent of the Year" và đang ngồi trong ban giám khảo Awwwards. Với một portfolio như thế này, kinh nghiệm đó là ranh giới giữa chuyển động phục vụ tác phẩm và chuyển động chôn vùi nó.

Đề bài: hình ảnh dẫn dắt, website tôn lên

Ảnh chân dung và tư liệu sống chết nhờ sự hiện diện — khoảnh khắc, biểu cảm, ánh sáng. Định hướng thiết kế là một nền gần như trắng tuyệt đối (bảng màu về cơ bản là #ffffff), nơi những bức ảnh là màu sắc duy nhất trong căn phòng. Ba ràng buộc định hình mọi quyết định kỹ thuật:

  • Không bao giờ làm giảm chất ảnh. Độ sắc nét là bất di bất dịch. Không hiệu ứng nào được phép làm mềm, nén hay crop ảnh theo kiểu mà nhiếp ảnh gia không gật đầu.
  • Chuyển động là dàn dựng, không phải trang trí. Loading transition, gallery reveal và trạng thái hover của menu đều phải có chủ đích — một chuỗi được đạo diễn, không phải đống thủ thuật rời rạc.
  • Nhanh dù ảnh nặng. Một site nhiếp ảnh, theo định nghĩa, là site nặng hàng megabyte. Nó vẫn phải tải nhanh và cuộn mượt 60fps trên laptop tầm trung lẫn điện thoại.

Phần craft: dựng chuyển động đẳng cấp giải thưởng trên nền WordPress

Đây là điều nhiều người bất ngờ khi xem dự án này: nó chạy trên WordPress. Có một định kiến dai dẳng rằng chuyển động đẳng cấp giải thưởng đòi hỏi một framework JavaScript tùy biến hoàn toàn, và rằng một CMS như WordPress sẽ kẹt ở mức "template". Không hề. Mẹo là xem WordPress như một lớp nội dung (content layer) và dựng trải nghiệm như một hệ thống motion front-end thực thụ ở phía trên — GSAP lo phần dàn dựng timeline và Three.js / WebGL lo phần render hình ảnh. Kết quả là một site mà chính nhiếp ảnh gia tự cập nhật được, mà vẫn cạnh tranh trên Awwwards.

Loading & page transition lấy ảnh làm trọng tâm

Ấn tượng đầu là transition từ loading sang nội dung, và trên một portfolio nó phải gánh hai việc: che thời gian tải asset giới thiệu bức ảnh đầu tiên như một khoảnh khắc hero. Nguyên tắc là coi cả chuỗi như một GSAP timeline duy nhất — loader, lớp phủ wipe và phần reveal ảnh đầu tiên được dàn dựng cùng nhau để mắt không bao giờ chạm vào một khung hình chết.

import gsap from 'gsap'

function introTimeline(onReady: () => void) {
  const tl = gsap.timeline({ defaults: { ease: 'expo.inOut', duration: 1 } })

  tl.to('[data-loader-bar]', { scaleX: 1, transformOrigin: 'left' })
    .add(onReady)                                          // nội dung đã mount sau lớp phủ
    .to('[data-loader]', { yPercent: -100 }, '+=0.05')    // nâng lớp phủ lên
    .from('[data-hero-image]', { scale: 1.08, autoAlpha: 0 }, '<0.15') // ảnh đầu tiên hạ cánh
    .from('[data-hero] [data-stagger]', { yPercent: 110, stagger: 0.05 }, '<0.2')

  return tl
}

Các tham số position ('<0.15', '<0.2') làm phần reveal ảnh hero chồng lên lúc lớp phủ nâng lên, nên bức ảnh đầu tiên đã yên vị trước khi loader biến mất. Sự chồng lớp đó chính là khác biệt giữa "trang đã tải xong" và "một trải nghiệm vừa bắt đầu".

WebGL tôn ảnh lên thay vì bóp ảnh đi

Three.js lo các xử lý ảnh nặng hơn — bao gồm những transition fluid, dựa trên distortion giữa các ảnh trong gallery. Quy tắc cứng từ đề bài (không bao giờ làm giảm chất ảnh) buộc phải có cách tiếp cận cụ thể: nạp texture ở độ phân giải đầy đủ và xử lý shader quanh tấm ảnh — một displacement fluid lúc chuyển cảnh, một cú "settle" tinh tế — thay vì thay đổi vĩnh viễn pixel gốc. Trên một WebGL plane nghĩa là phải tôn trọng device pixel ratio, color space và anisotropy để không gì bị mềm khi nhìn nghiêng:

import * as THREE from 'three'

const loader = new THREE.TextureLoader()
loader.load('/uploads/portrait.jpg', (texture) => {
  texture.colorSpace = THREE.SRGBColorSpace
  texture.anisotropy = renderer.capabilities.getMaxAnisotropy() // sắc nét ở mọi góc nhìn
  texture.minFilter = THREE.LinearMipmapLinearFilter
  texture.generateMipmaps = true
})

// Giới hạn DPR: trên 2 là trả chi phí fill-rate khổng lồ cho khác biệt gần như không ai thấy.
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))

Bản thân transition fluid là một fragment shader trộn giữa texture đi và texture đến bằng một giá trị displacement chạy theo progress — ảnh như chảy sang ảnh kế tiếp thay vì cắt cứng. Nếu bạn muốn hiểu cơ chế của lớp hiệu ứng này, tôi đã viết hẳn một bài về hiệu ứng displacement ảnh WebGL khi hover dùng đúng kỹ thuật GLSL đó.

Cuộn nhập vai và microinteraction của menu

Ngoài các WebGL plane, phần còn lại của site chạy bằng GSAP và ScrollTrigger: các item gallery nhô lên và yên vị khi vào viewport, còn trạng thái hover của menu — thứ mà cộng đồng Awwwards nhắc tới — chỉ animate trên transformopacity để luôn mượt. Quy tắc giữ cho một trang nhiều chuyển động, nặng ảnh vẫn nhanh thì nhàm chán nhưng tuyệt đối:

import { ScrollTrigger } from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger)

gsap.utils.toArray<HTMLElement>('[data-photo]').forEach((el) => {
  gsap.from(el, {
    yPercent: 12,
    autoAlpha: 0,
    ease: 'expo.out',
    duration: 1,
    scrollTrigger: { trigger: el, start: 'top 88%', once: true },
  })
})

Site nhiếp ảnh là kịch bản tệ nhất cho hiệu năng: ảnh lớn ở khắp nơi. Kỷ luật giữ cho nó nhanh:

  • Chỉ animate transformopacity. Chúng được GPU composite và bỏ qua layout/paint, nên main thread rảnh để cuộn qua hàng chục tấm ảnh.
  • Lazy-init WebGL. Scene Three.js chỉ khởi tạo khi một section gallery gần viewport, và tạm dừng vòng render khi cuộn ra ngoài màn hình — không đốt chu kỳ GPU cho thứ không nhìn thấy.
  • Texture responsive, có mipmap. Phục vụ ảnh đúng kích thước theo breakpoint và để mipmap lo việc downscale, để một bức chân dung không bao giờ gửi file 4000px xuống điện thoại.
  • Tôn trọng người xem. gsap.matchMedia() gỡ bỏ chuyển động nặng khi prefers-reduced-motion, giữ site dễ tiếp cận mà không phải tách code.

Kết quả: một Awwwards Honorable Mention

Site đoạt Awwwards Honorable Mention, với điểm cộng đồng trung bình khoảng 8.5, và được gắn thẻ về thiết kế tương tác và microinteraction. Bạn có thể xem trực tiếp tại mathijshanenkamp.com và trang giải thưởng trên Awwwards.

Sự ghi nhận đó nói lên điều cốt lõi của cả case study này: ban giám khảo tưởng thưởng một site mà nhiếp ảnh rõ ràng là ngôi sao, còn chuyển động là thứ làm nó trở nên điện ảnh. Với một nhiếp ảnh gia chân dung và tư liệu, đó chính là đề bài được thực thi chuẩn xác — tác phẩm dẫn dắt, trải nghiệm tôn lên.

Case study này thực ra nói về điều gì

Bài học có thể tổng quát hóa: chuyển động đẳng cấp giải thưởng là quyết định kỹ thuật front-end, không phải quyết định về stack. WordPress không kìm chân site này — một lớp GSAP + WebGL kỷ luật ở phía trên đã tạo ra trải nghiệm cạnh tranh với các bản dựng tùy biến hoàn toàn, đồng thời để nhiếp ảnh gia tự quản lý gallery của mình. Cùng một công thức — CMS quản lý nội dung, một hệ thống motion thực thụ, và kỷ luật hiệu năng tàn nhẫn — là thứ gánh mọi site thương hiệu hay portfolio nặng ảnh. Bạn có thể thấy nó được áp dụng khác đi trong case study kinetic typography Mat Voycewebsite sự kiện đoạt giải Iventions, còn nếu bạn đang tự dựng, bài cách làm portfolio đạt giải đi qua các nền tảng cơ bản.

FAQ

Website Mathijs Hanenkamp được dựng bằng gì?

WordPress làm lớp nội dung, GSAP điều khiển hệ thống motion và Three.js / WebGL lo các transition và render fluid của ảnh — một stack được chọn để nhiếp ảnh gia tự quản lý gallery, mà front end vẫn cho chuyển động đẳng cấp giải thưởng.

Có thể dựng site đạt Awwwards trên WordPress không?

Có. WordPress là lớp nội dung; trải nghiệm được dựng như một hệ thống motion front-end tùy biến (GSAP + WebGL) ở phía trên. Site này là minh chứng — nó đoạt Awwwards Honorable Mention khi chạy trên WordPress.

Ai thiết kế và phát triển site Mathijs Hanenkamp?

Đây là sự hợp tác giữa designer Huy Phan (thành viên ban giám khảo Awwwards) và Hon Tran ở vai trò creative developer, phụ trách front-end, motion GSAP và phần WebGL.

Làm sao thêm chuyển động cho site nhiếp ảnh mà không hại ảnh?

Nạp texture ở độ phân giải đầy đủ và xử lý shader quanh ảnh thay vì thay đổi pixel gốc, giới hạn device pixel ratio ở mức 2, dùng anisotropy và mipmap cho độ sắc nét, chỉ animate transform/opacity, và lazy-init WebGL để gallery nặng vẫn nhanh.

Cùng dựng thứ gì đó xứng tầm giải thưởng

Nếu bạn là nhiếp ảnh gia, thương hiệu hay agency cần một portfolio lấy ảnh làm trọng tâm hay site nhiếp ảnh WebGL tôn được tác phẩm thay vì tranh chấp với nó — đó chính là việc tôi làm với tư cách creative developer.


Viết bởi Hon Tran — creative developer, founder của hontran.dev, và thành viên ban giám khảo Awwwards. Hơn 11 năm dựng các trải nghiệm web đoạt giải, ưu tiên hiệu năng (GSAP, Three.js / WebGL, Next.js, WordPress) cho khách hàng toàn cầu. Lập trình viên Việt Nam đầu tiên đoạt giải web quốc tế. hontran.dev · Behance.