慣性聚合 関心のあるブログ、ニュース、テクノロジーを効率的に追跡
原文を読む 慣性聚合で開く

おすすめ購読元

小众软件
小众软件
博客园 - 叶小钗
有赞技术团队
有赞技术团队
大猫的无限游戏
大猫的无限游戏
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LangChain Blog
Hugging Face - Blog
Hugging Face - Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
aimingoo的专栏
aimingoo的专栏
Blog — PlanetScale
Blog — PlanetScale
爱范儿
爱范儿
T
Tailwind CSS Blog
Jina AI
Jina AI
量子位
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
J
Java Code Geeks
V
Visual Studio Blog
月光博客
月光博客

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python)
パート2:3.4MBのビデオを40kbのGSAPアニメーションに置き換える:カメラを追加
Sugam Panthi · 2026-05-28 · via DEV Community

第一部到達しました69,000r/webdevに関する見解を2日でまとめました。思わなかったです。40KBのDOMアニメーションで3.4MBの動画を置き換えることを書いたのは、それが共有に価値があると思ったからです。多くの人々が同じ問題について考えていることがわかりました。

コメントは投稿よりも良かった。人々はSEOインデックスングやスクリーンリーダーの挙動について尋ねた。prefers-reduced-motion のフォールバックについて、GSAP が本当に必要かどうか、そして数人が何かが足りないと指摘した。彼らは正しかった。

第一部では、平坦なステージ上でカーソルがシーンをクリックしていました。すべての動作は同じズームレベルで、観客から同じ距離で起こりました。実際の製品デモビデオを見ると、違う点に気づきます:カメラが動きます。重要なことが起こるとアクションにズームインし、ワークフローをカーソルに追従し、シーンが変わると引き戻ります。これがスライドデッキと指揮された映画の違いです。

この投稿ではカメラを追加しました。同じ40KBの予算です。ビデオファイルはありません.

4つのインタラクティブデモ、横並び比較、ライブFPSストレステストを含む完全な投稿を見てください

ズームラッパーの問題

最初に試すのはgsap.to(frame, { scale: 1.4 })です。半秒ほど動作しますが、その後レスポンシブスケーリングが消失するのを確認します。フィルムフレームはtransform: scale(filmScale) があり、GSAP はそれを上書きしました。両方は同じ CSS transform プロパティに書き込みます。同じ要素上で共存できません。

修正は、GSAP が所有するフレーム内のラッパーです。

<div data-film-frame style={{ transform: `scale(${filmScale})` }}>
  <div data-film-zoom className="origin-center">
    {/* All scene content */}
  </div>
  <Cursor />  {/* Outside the zoom wrapper */}
</div>

全画面モードに入る 全画面モードから退出する

GSAP がアニメーションを実行data-film-zoom 。外枠のレスポンシブスケールは変更されていません。カーソルはズームラッパーの外にあり、コンテンツがそれを囲んで拡大する際にサイズが同じままです。これを理解するのに、恥ずかしいほどの時間がかかりました。二つのdivです。それが全ての修正でした。

。 パンマス

フレームの中心にズームするのは簡単です。Pinterestのピンのような特定の要素にズームするのは実際の問題です。ズームラッパーを変換して、ターゲットが表示されるビューポートの中心に配置する必要があります:

const ZOOM = 1.45;
const panTo = (target) => ({
  x: (FILM_WIDTH / 2 - target.x) * (ZOOM - 1),
  y: (FILM_HEIGHT / 2 - target.y) * (ZOOM - 1),
});

フルスクリーンモードを開始 フルスクリーンモードを終了

ズーム1.0では翻訳は不要です。ズーム1.45では、中心から離れたピクセルはその距離の0.45倍の翻訳が必要です。

ズームを維持し、パンで追跡

最初の試みで最も大きな間違いは、一度のインタラクションでズームインし、ズームアウト、次のインタラクションで再びズームインし、再びズームアウトすることでした。それは予算の限られたズームトランジションのPowerPointのようでした。

正しいパターン: 一度ズームインし、ズームを維持し、カーソルを追って全てのインタラクションシーケンスにパンし、シーンを変更する際に一度ズームアウトする.

// Zoom in on right-click
tl.to(zoom, {
  scale: ZOOM, x: panPin.x, y: panPin.y,
  duration: 0.65, ease: "expo.out",
}, "zoomIn");

// Context menu while zoomed
tl.to(ctx, { autoAlpha: 1, duration: 0.16 }, "zoomIn+=0.35");

// Camera pans to follow cursor to the save button (still zoomed)
tl.to(zoom, {
  x: panSave.x, y: panSave.y,
  duration: 0.55, ease: "sine.inOut",
}, "panToSave");

// Only zoom out when done
tl.to(zoom, {
  scale: 1, x: 0, y: 0,
  duration: 0.45, ease: "sine.inOut",
}, "zoomOut");

フルスクリーンモードに入る フルスクリーンモードから退出する

フルポストでライブインタラクティブデモとしてこの動作を見る

イージングはすべてに適したものではない

第一部は使用されたpower2.out はほぼすべてのことに使えます。フラットなデモにはいいですが、カメラの動きを加えると、異なる動きのタイプには異なるイージングが必要で、そうしないと全体が不自然に感じられます。

動き イージング なぜ
カメラの回転 sine.inOut 最も滑らかな曲線。本物のカメラがドーリーに乗っているような感覚です。
効果的なズームイン expo.out 早い始まり、長い減速。ブシュッと音が鳴り、落ち着きます。
カーソルの移動 sine.inOut 自然な手の加速度
フェードイン sine.out 可視化に減速
クリックスqueeze power2.out 反応が速い押し付け
クリックの解放 back.out(2.2) わずかなオーバーシュート。物理的な感覚
タイプされたテキスト none 実際のタイピングが楽にならない

最も大きなアップグレードは、カメラの動きにおいてpower2.inOutsine.inOutに置き換えたことです。power2には、大きなスケールで機械的だと感じる目立ちやすい加速があります。sineは、曲線のどこにいても認識できるようなキックはありません。

カーソルは決して無効になりません

カメラの動きにおいて、シーンが切り替わる瞬間でカーソルが固着している場面があります。それらの瞬間はイリュージョンを壊します。各カメラの動きには、同じタイムラインラベルでの同時のカーソルの動きが必要です:

// BAD: cursor is dead during zoom
tl.to(zoom, { scale: 1.4, x: panX, y: panY, duration: 0.7 }, "zoomIn");

// GOOD: cursor drifts toward its next target during zoom
tl.to(zoom, {
  scale: 1.4, x: panX, y: panY,
  duration: 0.7, ease: "expo.out",
}, "zoomIn");
tl.to(cursor, {
  x: current.x + (next.x - current.x) * 0.3,
  y: current.y + (next.y - current.y) * 0.3,
  duration: 0.65, ease: "sine.out",
}, "zoomIn");

フルスクリーンモードに入る フルスクリーンモードを終了する

カーソルが到着する必要はありません。次のターゲットへの20~30%のずれで十分です。落ち着いていますが、決して死んでいません。

全体的投稿には、ズーム中のフリーズしたカーソルとドリフトするカーソルの横並び比較があります

優雅なループ

第一部のループは急な動きでした。カメラの動きでは問題が悪化します。ズームが1.4倍から1.0倍に瞬時にジャンプするからです

対処法はアウトロです

tl.to(zoom, { scale: 1, x: 0, y: 0, duration: 0.8, ease: "sine.inOut" }, "outro");
tl.to(cursor, { x: offScreenX, y: offScreenY, duration: 0.7, ease: "sine.in" }, "outro+=0.1");
tl.to({}, { duration: 0.6 }); // breathing room

フルスクリーンモードに入る フルスクリーンモードを出る

タイミングに関するルール:最初の草稿は常に遅すぎる。最初の動作するバージョン後には、タイミングから20-30%削減する.

SEO、テーマング、そして動画ができないこと

<video>タグでソースを表示してGoogleが見る<video src="demo.mp4">。黒い箱。GSAPデモでソースを確認すると、すべてのボタンのラベル、メニュー項目、ヘッディングがインデックス可能なテキストです。制御されたランキングテストは行っていませんが、論理的には:実際のDOMテキストは不透明なバイナリボリュームを上回ります。

インデックス化を超えて、製品が変わるたびにDOMデモが変わります。マーケティングがボタンのラベルを変更した?テキスト文字列を変更します。ブランドカラーの更新?1つの16進値です。デモのボタンが実際にコンバートするようにしたい?実際のサインアップモーダルに接続します。ビデオはそれらを何もできない

アクセシビリティ

prefers-reduced-motion: reduceが有効な場合、タイムライン全体をスキップし、静止状態をレンダリングします。GSAPのautoAlphaは両方を設定しますopacity: 0visibility: hidden をタブ順序とスクリーンリーダーから削除します。隠れた要素はすべて autoAlpha を使用し、opacity は使用しません。そのため、スクリーンリーダーは現在表示されているものだけを見ます。

GSAPが必要ですか?

単純なアニメーションの場合は不要ですが、ウェブクリッパーデモにはカメラの動きを含む2つのシーンで約50個の連携アニメーションがあります。GSAPはあなたにラベル(名前付きビート)を提供します。repeat: -1、データ属性クエリ用のgsap.utils.selector(root)、完全なイージングライブラリ、およびステッカー。これらをすべてGSAPなしで構築することもできます。もっと時間がかかり、結果も悪くなります。

GSAPのコアは28 KB gzippedです。50アニメーションを含むシネマティックデモをオーケストレートしている場合、それはインフラストラクチャです。

エージェント現実

サイト全体で5つのデモ、約4,000行の振り付けコードです。そのうち約60%は私が書きました。残りの40%はAIエージェントが書きました

私の60%は監督で、ズームインするものを決めたり、両方のオプションを見てスムーズ化を選んだり、ズームイン中にカーソルが動きにくいことに気づいたり、「ズームアウトが200ms遅すぎる」と言ったりしました。エージェントはアニメーションを見て何かがおかしいと感じることはできません。

エージェントの40%は実装でした:タイムラインコード1,500行、DOM要素、クリックヘルパー、リセットブロック。スキルファイルで定義したルールに従ったパターンに基づく作業。パターンは十分に安定しているため、異なるデモ間で出力が一貫しています。しかし、エージェントは何かが間違っているかどうかを知ることはできません。その部分はまだ私のものです.

パフォーマンス

ウェブクリッパーのデモには50 .to()の呼び出しがありますが、フレームごとに3-5つだけアクティブにトゥイーンしています。毎回.to()transformまたはopacityに書き込み、どちらもコンポジターフレンドリーです。フルポストにはFPSカウンター付きのライブストレステストがあり、8から48の並列要素を押し込み、フレームレートを監視できます。更新された数学

アプローチ 圧縮 カメラ? インデックス可能? アクセス可能? テーマ可能?
GSAP(フラット、第一部) ~37 KB いいえ はい はい はい
GSAP(パン&ズーム、第二部) ~40 KB はい はい はい はい
15秒 MP4 (H.264) 2-4 MB 内蔵 いいえ いいえ いいえ
15秒 WebM (VP9) 1-2 MB 内蔵 いいえ いいえ いいえ
15秒 GIF 8~15 MB 焼き込まれて いいえ いいえ いいえ

カメラを追加すると、バンドルに約3 KBが追加されます。costumary.comの全5つの生産デモが圧縮後合計80 KB未満です。これに相当する動画のサイズは15~20 MBです。

第一部は動画を置き換えられることを証明した。第二部はそれが録画ではなく指示されたように感じ始める部分だ。

初期コストは現実的。継続コストはほぼゼロ。アップデートはコードの変更ではなく再録画ではない。


インタラクティブデモを含む全文: spanthi.com/blog/gsap-choreography-part-2

プロダクション例: costumary.com | costumary.com/web-clipper

オープンソースエージェントスキル: gsap-choreography