Nahorniak Templates
База референсів шаблонів і компонентів
Назад до шаблону · Davies - Personal Portfolio HTML Template
c96

award-flip-images

Галерея·Шаблон: Davies - Personal Portfolio HTML Template·Складність анімації: heavy·Адаптивний: Так
award-flip-images

Файли-джерела

  • index.htmlsection.section-award

Бібліотеки

gsapscrolltriggerswiper

Summary

The Award section opens with a vertical award-count swiper (Behance x28, Awwwards x41, CSS Design Awards x67) cycling on autoplay. Below it, six photos start stacked at the parent's centre, then a GSAP timeline first lifts them to centre and then fans them out along an arc with per-index x/y offsets, rotation, rotateX and rotateY for a faux-3D shuffle.

HTML structure (minimal)

<section class="section-award flat-spacing">
  <div class="container">
    <div class="row">
      <div class="col-md-5 ms-auto">
        <div class="col-right">
          <h6 class="mini-title text-caption text-white-64">AWARDS</h6>
          <h5 class="text-color-change">Since 2020, my work has been honored…</h5>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-md-5">
        <p class="desc text-white-64 mini-title">157 industry awards.<br>Bold ideas. Flawless execution.</p>
        <div dir="ltr" class="swiper tf-swiper" data-preview="3" data-loop="true" data-auto="true" data-delay="1000" data-direction="vertical" data-space="4">
          <div class="swiper-wrapper">
            <div class="swiper-slide"><div class="award-item h4">Behance <span class="text-body-1">x28</span></div></div>
            <div class="swiper-slide"><div class="award-item h4">Awwwards <span class="text-body-1">x41</span></div></div>
            <!-- … -->
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="wrap-flip-image flat-spacing">
    <div class="container">
      <div class="flip-image-list gsap-anime-2">
        <div class="flip-image"><img src="assets/images/section/award-1.jpg" alt=""></div>
        <div class="flip-image"><img src="assets/images/section/award-2.jpg" alt=""></div>
        <!-- 6 total -->
      </div>
    </div>
  </div>
</section>

Key SCSS tokens

.flip-image-list {
  position: relative;
  height: 360px;
  perspective: 1200px;
}

.flip-image {
  width: 325px;
  height: 325px;
  border-radius: 12px;
  overflow: hidden;
  opacity: 0;
  img { width: 100%; height: 100%; object-fit: cover; }
}

Animation logic

// assets/js/gsapAnimation.js — gsapA2()
const cards = document.querySelectorAll('.flip-image');
function animate() {
  const isMobile = window.innerWidth < 767;
  const cardW = isMobile ? 150 : 325;
  const parent = cards[0].parentElement;
  const centerX = parent.clientWidth / 2 - cardW / 2;
  const centerY = parent.clientHeight / 2 - cardW / 2;

  cards.forEach((card, i) => { card.style.position = 'absolute'; card.style.zIndex = i + 1; });

  const tl = gsap.timeline({
    defaults: { ease: 'power3.out' },
    scrollTrigger: { trigger: '.gsap-anime-2', start: 'top 80%', toggleActions: 'play none none reverse' },
  });
  tl.to(cards, { x: centerX, y: centerY, opacity: 1, duration: 1, stagger: 0.1 })
    .to(cards, {
      x: (i) => centerX + [-400, -240, -80, 80, 240, 400][i],
      y: (i) => centerY + [-300, -180, -60, 60, 180, 300][i],
      rotation: -10,
      rotateX: 4,
      rotateY: 10,
      duration: 1,
      ease: 'power2.out',
      delay: 0.3,
    });
}
animate();
window.addEventListener('resize', () => { gsap.killTweensOf('.flip-image'); animate(); });

Notable details

  • Two-stage timeline: gather to centre, then explode in an arc — the second tween's per-index values give the cards a subtle physical "fan" instead of a uniform spread.
  • rotateX: 4, rotateY: 10 plus the parent's perspective: 1200px give a faux-3D shuffle without actually doing CSS 3D layout.
  • Function-based tween values let one timeline drive different per-index destinations without unrolling six tweens.
  • Resize handler kills tweens and re-runs animate() — preventing stuck offsets if the user resizes mid-animation.

Use when

  • Award walls, image showcases, or "deck of cards" reveals where the cards should fan from a stack as the user scrolls.
  • Galleries with a fixed small count (4–8) where per-index positioning is acceptable.

Caveats

  • The exploded positions are hardcoded for six cards — adding or removing cards requires editing the offset arrays.
  • parent.style.position = 'relative' is set imperatively — works but mutates DOM style; consider doing this in CSS.
  • ScrollTrigger relies on the .gsap-anime-2 parent reaching top 80%; very tall headers above can defer this trigger longer than expected.