乐于分享
好东西不私藏

洞口跳跃(可复制源代码)

洞口跳跃(可复制源代码)

效果演示

文末可一键复制完整代码

源代码

<!DOCTYPE html><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>洞口跳跃</title><scriptsrc="https://unpkg.com/gsap@3/dist/gsap.min.js"></script><scriptsrc="https://unpkg.com/gsap@3/dist/ScrollTrigger.min.js"></script><scriptsrc="https://unpkg.com/gsap@3/dist/GSDevTools.min.js"></script><style>@import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,200..800&display=swap'); * { box-sizing: border-box; } body { min-height100vhdisplay: flex; justify-content: center; align-items: center; color#fffbackground-color#222font-family"Bricolage Grotesque", sans-serif; } .container { border-radius30pxwidth400pxheight300pxposition: relative; --bg-dark#ffc762--bg-light#ffe9a4background-imagelinear-gradient(135deg, var(--bg-light) 25%, transparent 25%), linear-gradient(225deg, var(--bg-light) 25%, transparent 25%), linear-gradient(45deg, var(--bg-light) 25%, transparent 25%), linear-gradient(315deg, var(--bg-light) 25%var(--bg-dark) 25%); background-position15px015px00000background-size30px30pxbackground-repeat: repeat; --top-spacecalc(300px * 0.7); --hole-width150px--hole-height20px; } .inner-box { position: absolute; top3pxleft0right0width80%heightcalc(var(--top-space) + var(--hole-height) / 2); margin: auto; border-radius50%overflow: hidden; } .hole { position: absolute; topvar(--top-space); left0right0margin: auto; widthvar(--hole-width); heightvar(--hole-height); background-color#000dborder-radius50%; } .shadow { position: absolute; topvar(--top-space); left0right0margin: auto; widthvar(--hole-width); heightvar(--hole-height); background-imageradial-gradient(#0008, transparent 75%); border-radius50%opacity0; } .emoji { position: absolute; bottom0left0right0margin: auto; width: fit-content; font-size80px; }</style></head><body><divclass="container"><divclass="hole"></div><divclass="shadow"></div><divclass="inner-box"><divclass="emoji">🎃</div></div></div><script>            (() => { gsap.registerPlugin(GSDevTools); const tl = gsap.timeline({ repeat1yoyotruerepeatDelay0.5, }); tl.from('.hole', { scale0repeat1yoyotrue, }) .fromTo('.emoji', { y140scaleY2 }, { y-120scaleY1 }, 0.2) .to('.emoji', { y10ease'power1.in' }, '>') .to( '.emoji', { scaleY0.8scaleX1.2transformOrigin'center bottom'repeat1yoyotrueduration0.2 }) .to('.shadow', { opacity1duration0.2 }, 0.7) .to('.shadow', { scaleX0.7ease'power1.in' }, '>') })();</script></body></html>

实现思路拆分

洞口跳跃是怎么画出来的?

洞口跳跃(gsap hole jumper animation)用 GSAP 时间轴驱动 🎃 从洞口弹出、拉伸、落地弹跳,洞口与阴影同步缩放,形成卡通式 jump 动画。

说白了就三件事

  1. HTML.container 棋盘格背景 + 椭圆 .hole + .shadow + .inner-box 裁剪入口内的 .emoji
  2. CSS:CSS 变量定洞口位置与尺寸;inner-box 上半圆 overflow: hidden 形成「探出」入口。
  3. JavaScript:GSAP timeline repeat + yoyo,串联 hole 缩放、emoji 位移/挤压、shadow 显隐与缩放。

改节奏动 timeline 的 repeatDelay 与各 tween duration,改洞口动 --hole-width / --top-space

颜色为啥长这样

  • 背景:深灰 #222 页面,容器暖黄棋盘 #ffc762 / #ffe9a4
  • 洞口:半透明黑 #000d 椭圆
  • 阴影:径向渐变 #0008 → transparent
  • 主体:🎃 emoji 80px
  • 整体万圣节暖色调、卡通弹性

动起来是啥感觉

循环播放:洞口出现 → 南瓜从下方弹起 → 越过洞口 → 落回 → 挤压弹跳 → 倒放 yoyo。

  • 洞口 scale: 0 → 1 先展开
  • emoji 从 y: 140, scaleY: 2 拉伸弹出到 y: -120
  • 落至 y: 10 后 scaleY/X 挤压弹跳
  • shadow 随跳跃显隐并 scaleX 收窄
  • repeat: 1, yoyo: true 往返循环,间隔 0.5s

怎么一层层画出来

场景结构
  1. .container:400×300 圆角卡片,斜纹棋盘 background。
  2. .inner-box:顶部 70% 处椭圆裁剪区,emoji 从底部向上探出。
  3. .hole + .shadow:同一位置叠放,shadow 用 radial-gradient。
GSAP 时间轴
  1. tl.from('.hole', { scale: 0, repeat: 1, yoyo }) 洞口呼吸。
  2. .fromTo('.emoji', ...) 拉伸上升,与 hole 略错开 0.2s。
  3. .to('.emoji', { y: 10, ease: 'power1.in' }) 落地。
  4. scaleY/X yoyo 挤压弹跳;shadow opacity + scaleX 配合落地。

源码获取