→ לכל המאגר

G82 · הטיה לפי מהירות הגלילה

GSAP GSAP · ScrollTrigger velocity תמונות וגלריותכרטיסים ממתין

כרטיסים או תמונות שנוטים קלות בכיוון הגלילה ככל שגוללים מהר, ומתיישרים ברגע שעוצרים. העמוד מרגיש שיש לו משקל.

מתי משתמשים: גריד עבודות, רשימת מוצרים, פיד תמונות. כל מה שגוללים דרכו מהר. לא על טקסט רץ.

הדמו כאן עיצובי-ניטרלי בכוונה. כשהמהלך נכנס לפרויקט, מיובאת רק ההתנהגות: הצבעים, הרדיוסים, הפונטים והצללים יורשים את העיצוב של אותו פרויקט.

הדמו

גלול למטה, הדמו מגיע ↓
1
2
3
4
5
6
7
8
9
עוד מסלול גלילה. נסה גם חזרה למעלה ↑
getVelocity של ScrollTrigger נדגם בכל אירוע גלילה וממופה ל-skewY של עד 6 מעלות, עם quickTo שמחזיר לאפס. במובייל הגלילה מהירה יותר ולכן המקסימום יורד ל-3 מעלות.

קוד להדבקה

הקוד כאן עומד בפני עצמו. כל טוקן עיצוב נושא ברירת מחדל, מחלקות העזר של המאגר מוטמעות בו, ותגי הסקריפט מסודרים לפי הסדר הנכון. פרויקט שמגדיר --accent או --line משלו יורש אותם אוטומטית.

פתח קובץ עצמאי ↗
הצג את הקוד כאן

CSS

/* מחלקות עזר של המאגר שהרכיב הזה משתמש בהן */
.stage{padding:var(--sec, clamp(120px, 12vw, 260px)) var(--gutter, clamp(24px, 5vw, 96px));position:relative}
.stage.tight{padding-block:clamp(48px,5vw,90px)}
.stage.full{padding-inline:0}
.ph{display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;border-radius:var(--r, 14px)}
.ph-a{background:linear-gradient(160deg,#3b5bdb,#748ffc)}
.ph-b{background:linear-gradient(160deg,#5f3dc4,#9775fa)}
.ph-c{background:linear-gradient(160deg,#0b7285,#3bc9db)}
.ph-d{background:linear-gradient(160deg,#2b8a3e,#69db7c)}
.ph-e{background:linear-gradient(160deg,#e8590c,#ffa94d)}
.ph-l{background:rgba(16,18,43,.72);color:#fff;padding:.18em .7em;border-radius:999px;line-height:1.3;font-size:max(.78em,12px)}

/* G82 · הטיה לפי מהירות הגלילה */
.sk-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--gap, clamp(16px, 1.6vw, 36px));padding-block:10vh 30vh}
.sk-it{aspect-ratio:3/4;border-radius:var(--r, 14px);overflow:hidden;will-change:transform}
.sk-it .ph{width:100%;height:100%;font-size:22px}
@media(max-width:767px){.sk-grid{grid-template-columns:1fr 1fr}}

HTML

<div class="stage tight"><div class="sk-grid">
  <div class="sk-it"><div class="ph ph-a"><span class="ph-l">1</span></div></div><div class="sk-it"><div class="ph ph-b"><span class="ph-l">2</span></div></div><div class="sk-it"><div class="ph ph-c"><span class="ph-l">3</span></div></div>
  <div class="sk-it"><div class="ph ph-d"><span class="ph-l">4</span></div></div><div class="sk-it"><div class="ph ph-e"><span class="ph-l">5</span></div></div><div class="sk-it"><div class="ph ph-a"><span class="ph-l">6</span></div></div>
  <div class="sk-it"><div class="ph ph-b"><span class="ph-l">7</span></div></div><div class="sk-it"><div class="ph ph-c"><span class="ph-l">8</span></div></div><div class="sk-it"><div class="ph ph-d"><span class="ph-l">9</span></div></div>
</div></div>

JS

gsap.registerPlugin(ScrollTrigger);

(function(){
  if(matchMedia("(prefers-reduced-motion: reduce)").matches)return;
  const items=gsap.utils.toArray(".sk-it"),MAX=matchMedia("(max-width:767px)").matches?3:6;
  const skew=gsap.quickTo(items,"skewY",{duration:.5,ease:"power3.out"});
  const clamp=gsap.utils.clamp(-MAX,MAX);
  ScrollTrigger.create({onUpdate:s=>{ skew(clamp(s.getVelocity()/-300)); }});
  // כשהגלילה נעצרת אין onUpdate, ולכן מחזירים לאפס דרך טיימר קצר
  let t; addEventListener("scroll",()=>{clearTimeout(t);t=setTimeout(()=>skew(0),120);},{passive:true});
})();