{}const=>[]async()letfn</>var
開発モバイル

「Tinkoff/Yandexのように」作る方法:アプリをすぐに「高価」に見せるアニメーションとマイクロインタラクション

デザイナーである必要はなく、3Dを知る必要もありません。シンプルなCSSアニメーションとJavaScriptのトリックで、アプリケーションのレベルをすぐに上げることができます。ボタンからモーダルウィンドウまで、コードと説明付きのステップバイステップガイド。

К

Kodik

著者

3分で読める

Tinkoff、Yandex、Alfa-Bankのアプリがどれほど使いやすいか、気づいていますか?ボタンは押すと反応し、要素はスムーズに表示され、読み込みはイライラするものではなく、むしろ目を見張るようなものです。これは魔法でもデザイナーの軍隊でもありません。これは、あなたが習得できる具体的なテクニックのセットです。

なぜこれが重要なのでしょうか?

ユーザーは「わあ、これは立体的なベジエ曲線のトランジションだ!」とは言いません。しかし、「なんて素敵なアプリなんだ」とか「なんか安っぽいね」とか言うでしょう。質の高いアニメーションは無意識のレベルで機能します。

  • スピード感を演出する — サーバーが遅くても

  • フィードバックを提供する — ユーザーは、自分のアクションが考慮されていることを理解している

  • 認知負荷を軽減する スムーズなトランジションは、脳が起こっていることを理解するのに役立ちます

  • 信頼できる — 細部にまでこだわっていることが、チームが製品に配慮していることを示している

🔥 10万人以上の学生が参加中

理論を読むのに疲れた?
コーディングの時間だ!

Kodik — 実践でプログラミングを学ぶアプリ。AIメンター、インタラクティブなレッスン、実際のプロジェクト。

🤖 AI 24時間
🎓 修了証
💰 無料
🚀 始める
今日参加

1. スピナーの代わりにスケルトン

スピナーの何が悪いのですか?

回転する円は何の情報も与えません。ユーザーは、どれくらい待つべきか、何が読み込まれているのかを知りません。

Tinkoffで行うこと:

将来のコンテンツの「幽霊」を示します。テキスト、画像、ボタンの場所に灰色のブロックが表示されます。これはスケルトン画面と呼ばれます。

.skeleton {
  background: linear-gradient(
    90deg,
    #f0f0f0 25%,
    #e0e0e0 50%,
    #f0f0f0 75%
  );
  background-size: 200% 100%;
  animation: loading 1.5s infinite;
  border-radius: 4px;
}

@keyframes loading {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

なぜこれが機能するのか:

脳はスケルトンを「コンテンツがほぼ読み込まれている」と認識し、「どれくらい待つ必要があるかわからない」とは認識しません。調査によると、ユーザーはスピナーよりもスケルトンの方が読み込み時間が30〜40%速いと評価しています。

2. アクションに対する触覚応答

ボタンを押す効果:

Yandexアプリでボタンを押すと、少し「落ち込む」ように見えます。これは物理的なボタンを模倣しています。

.button {
  background: #ffdd2d;
  border: none;
  padding: 12px 24px;
  border-radius: 8px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.button:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
}

.button:active {
  transform: translateY(0);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

リップル効果(波):

クリックすると、クリックしたポイントから波が広がります。これはマテリアルデザインの機能ですが、誰もが使用しています。

function createRipple(event) {
  const button = event.currentTarget;
  const circle = document.createElement('span');
  const diameter = Math.max(button.clientWidth, button.clientHeight);
  const radius = diameter / 2;

  circle.style.width = circle.style.height = `${diameter}px`;
  circle.style.left = `${event.clientX - button.offsetLeft - radius}px`;
  circle.style.top = `${event.clientY - button.offsetTop - radius}px`;
  circle.classList.add('ripple');

  const ripple = button.getElementsByClassName('ripple')[0];
  if (ripple) {
    ripple.remove();
  }

  button.appendChild(circle);
}

3. ステート間のスマートな移行

悪い点:

コンテンツは消えたり現れたりします。急に。安く。

良い:

transformとopacityを使用してスムーズなトランジションを実現します。

.fade-enter {
  opacity: 0;
  transform: translateY(10px);
}

.fade-enter-active {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.fade-enter-to {
  opacity: 1;
  transform: translateY(0);
}

黄金律: DOMの変更はすべてアニメーション化する必要があります。突然の出現/消滅はありません。

4. 形状のマイクロアニメーション

入力にフォーカスした場合:

.input {
  border: 2px solid #e0e0e0;
  padding: 12px;
  width: 100%;
  transition: all 0.2s ease;
  outline: none;
}

.input:focus {
  border-color: #ffdd2d;
  box-shadow: 0 0 0 4px rgba(255, 221, 45, 0.1);
}

.input-label {
  position: absolute;
  left: 12px;
  top: 12px;
  color: #999;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  pointer-events: none;
}

.input:focus + .input-label,
.input:not(:placeholder-shown) + .input-label {
  top: -8px;
  left: 8px;
  font-size: 12px;
  background: white;
  padding: 0 4px;
  color: #ffdd2d;
}

アニメーションによる検証:

.input-error {
  border-color: #ff3333;
  animation: shake 0.4s;
}

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
  20%, 40%, 60%, 80% { transform: translateX(5px); }
}

5. 怒らないプログレスバー

悪い進捗バー: ただ動いているだけ。つまらない。

良い進捗バー: 滑らかで、わずかな輝きがあり、特定のステージを示します。

.progress-bar {
  width: 100%;
  height: 6px;
  background: #f0f0f0;
  border-radius: 10px;
  overflow: hidden;
  position: relative;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #ffdd2d, #ffc700);
  border-radius: 10px;
  transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  box-shadow: 0 0 10px rgba(255, 221, 45, 0.5);
}

6.スマートアピアランスのモーダルウィンドウ

間違い: ウィンドウが表示されます。

正しい: 背景が暗くなり、ウィンドウがわずかに拡大されて下から上に移動します。

.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.3s ease;
  pointer-events: none;
}

.modal-overlay.active {
  background: rgba(0, 0, 0, 0.5);
  pointer-events: all;
}

.modal {
  background: white;
  border-radius: 16px;
  padding: 24px;
  max-width: 500px;
  width: 90%;
  transform: scale(0.9) translateY(20px);
  opacity: 0;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.modal-overlay.active .modal {
  transform: scale(1) translateY(0);
  opacity: 1;
}

7. ホバー効果のあるカード

商品、投稿、プロジェクトのカードは、マウスオーバーに反応する必要があります。

.card {
  background: white;
  border-radius: 12px;
  padding: 20px;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}

.card img {
  transition: transform 0.3s ease;
}

.card:hover img {
  transform: scale(1.05);
}

8. アクションの読み込みインジケーター

ユーザーが「送信」をクリックすると、ボタンはプロセスが進行中であることを示す必要があります。

.submit-button {
  position: relative;
  min-width: 120px;
  transition: all 0.3s ease;
}

.submit-button.loading {
  pointer-events: none;
}

.spinner {
  width: 20px;
  height: 20px;
  animation: rotate 1s linear infinite;
}

@keyframes rotate {
  100% { transform: rotate(360deg); }
}

9.トーストと通知

原則:

  • サイドバー(右上または左上)

  • スムーズに入る

  • 3 ~ 5 秒後に自動的に消えます

  • 手動で閉じることができます

.toast {
  position: fixed;
  top: 20px;
  right: -300px;
  background: white;
  padding: 16px 20px;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  min-width: 250px;
  transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.toast.show {
  right: 20px;
}

10. アニメーションの重要な原則

Timing functions (時間関数):

easeまたはlinearを単に使用しないでください。キュービックベジエを学びましょう。

  • ease-in-out — スムーズに加速・減速

  • cubic-bezier(0.4, 0, 0.2, 1) - 素材デザインの緩和、非常に快適

  • cubic-bezier(0.25, 0.46, 0.45, 0.94) - 高速アニメーション用のeaseOutQuad

期間:

  • マイクロインタラクション (ホバー、クリック):100〜200ミリ秒

  • 状態間の移行: 200-300ms

  • モーダルウィンドウ、ドロワー: 300-400ms

  • ページアニメーション: 400-600ms

600ms以上は遅すぎます。

60 FPSルール:

リフローを引き起こさないプロパティのみをアニメーション化します。

  • transform, opacity

  • width, height, top, left, margin

結論

高品質のアニメーションは、複雑さではなく、細部にこだわっています。3Dや物理を学ぶ必要はありません。必要なのは:

  1. すべてに滑らかさを追加する

  2. 行動に対するフィードバックを与える

  3. 正しいタイミング関数を使用する

  4. 一貫性を保つ

1つのボタンから始めましょう。それを楽しくしましょう。それからもう一つ。それからフォーム。それからカード。1か月後、あなたのアプリは素晴らしいものになるでしょう。

これらすべて、そしてさらに多くのことを学ぶことができます コディケ — 実践的な課題と実際の例を交えて詳しく説明します。私たちは理論を分析するだけでなく、実際のプロジェクトでどのように機能するかを示します。

サポートや質問、コードについての相談が必要な場合は、 巨大なアクティブコミュニティ Telegramチャンネル! 常に支援、アドバイス、サポートを提供する2000人以上の開発者。

👉 コディックで学習を開始する 🔥 Telegramに参加する

🎯先延ばしをやめよう

記事は気に入った?
実践の時間だ!

Kodikでは読むだけでなく、すぐにコードを書く。理論 + 実践 = 本当のスキル。

即座に実践
🧠AIがコードを説明
🏆修了証

登録不要 • カード不要