GODRICH
#cssアニメーション#ボタン#ローディング#トランジション#スクロール#ダッシュボード#実用ui#デザイントレンド

導入事例 web デザイン9選 — 成果数値まで計算して見せる

導入事例 web デザインは色や余白より先に、数字がどう動くかで差がつきます。画面に入った瞬間から成果数値がフレームごとに求め直されカウントアップし、事例ごとに計算したインパクトスコアでグリッドタイルの大きさが決まり、引用文の長さに合わせてフォントサイズが逆算される、事例ページ用セクション9種です。

自動再生 · タイルを押すとその項目へ · すべて1つのzip

デモ

9項目とも「見た目の演出ではなく、成果数値・before/afterの差・引用文の長さ・業種別件数・タグの重なり数・ロゴ列の実測幅というデータを計算し直してカウントアップする数字・タイルの大きさ・ゲージの角度・フォントサイズ・下線の座標・並び順・ループ時間・平均値に反映する」という同じ前提を共有しています。実測値は次のとおりです。

番号 項目 累積面積 強度平均 動いたフレーム
01 事例ヒーロー 6.48% 165.7 17/23
02 ストーリーグリッド 52.50% 46.9 7/23
03 メトリックハイライト 2.33% 128.3 17/23
04 引用ブロック 7.08% 77.7 10/23
05 業種タブ 2.14% 143.3 9/23
06 ビデオカード 31.47% 103.1 23/23
07 関連CTA 18.35% 59.7 8/23
08 ロゴバー 3.00% 130.8 23/23
09 事例フッター 0.79% 108.2 8/23

02ストーリーグリッドが累積面積52.50%で最も広いのは、タイルのgrid-column/grid-rowのspanごとグリッド全体を組み替えるためです。09事例フッターが0.79%・05業種タブが2.14%・03メトリックハイライトが2.33%と狭いのは、変わる領域がそれぞれ要約バッジの数字・下線の帯・ゲージ針だけに限られる構造上の値で、この3項目の狭さは欠陥ではありません。動いたフレームは02ストーリーグリッド・07関連CTA・09事例フッターが7〜8フレームで最も少なく、これはシナリオが600〜1600msごとに1回しか切り替わらない構造上の待機区間です。反対に06ビデオカードと08ロゴバーは23フレームすべてで動き、06はスクロール位置の割合を毎フレーム読み直してキャンバスを描き直し、08はCSSマーキーが流れ続けるため強度平均も130.8まで上がります。強度平均は02が46.9で最も落ち着き、01事例ヒーローが165.7で最も明るくなっています。9項目とも下限を満たしています。

事例ページの解剖 — 9つのセクションが計算するもの

「事例ページ デザイン」で検索して出てくるものの多くは、写真とロゴを並べただけの静的な型です。ここで扱う9つのセクションは、その手前に計算の層を1枚重ねます。成果数値・before/afterの差・引用文の長さ・業種別件数・タグの重なり・ロゴ列の実測幅というデータを毎回読み直し、カウントアップする数字・タイルの大きさ・ゲージの角度・フォントサイズ・下線の座標・並び順・ループ時間・平均値に変換し直す設計です。

何が入力で何が出力か

入力は成果数値・before/afterの値・引用文の文字数・業種別の件数・タグの重なり数・ロゴの実測幅の6種類です。出力はCSS変数か、DOMに直接書き込むテキスト・transformのどちらかで、レイアウトのキーフレーム自体は変えません。

なぜ一枚の層に計算をまとめるのか

インパクトスコアの正規化を各所に散らすと、データセットを差し替えるたびに複数箇所を直す必要が出ます。applyのような専用の計算関数に集めておけば、データが変わってもその関数を呼び直すだけで表示全体のつじつまが揃います。実績紹介ページを自作するときも、同じように計算をひとつの層にまとめておくと差し替えが楽になります。

セクション別コード

導入事例 デザインを探して来た人は、まずこの9項目の実装から見ると早いです。実際のユーザー操作に反応するのは05業種タブ(クリック)と06ビデオカード(スクロール+再生ボタン)だけで、残り7項目はsetIntervalによる自動循環です。プロジェクト名・引用者・タグは名前付きの配列定数で定義してあり、実在の企業も実際の動画ファイルもどこにも入っていません。

01事例ヒーロー — 成果数値をフレームごとに求め直してカウントアップする最上部

TARGET128に対してEASE_POW2のイージング1-(1-t)^2をANIM_MS1300msかけて通し、経過比率tから値を毎フレーム求め直しながら0から目標値までカウントアップします。CYCLE_MS1900msごとにこの循環が自動で繰り返され、クリックなどのユーザー操作は必要ありません。

事例ヒーロー — 成果数値をフレームごとに求め直してカウントアップする最上部
新しいタブで開く

01 · 事例ヒーロー — 成果数値をフレームごとに求め直してカウントアップする最上部 — 計測 累積面積 6.476% · 動いたフレーム 17/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

getContext('2d')measureTextrequestAnimationFrame

TARGET128とEASE_POW2が作るカウントアップ曲線

runCycleはapplyValue(0)で値をリセットしてからrequestAnimationFrameのループに入り、tが1に達した瞬間に自ら止まります。

function runCycle() {
  if (reduce) { applyValue(TARGET); return; }
  var start = null;
  function frame(ts) {
    if (start === null) start = ts;
    var t = Math.min((ts - start) / ANIM_MS, 1);
    var eased = 1 - Math.pow(1 - t, EASE_POW);
    var val = Math.round(TARGET * eased);
    applyValue(val);
    if (t < 1) requestAnimationFrame(frame);
  }
  applyValue(0);
  requestAnimationFrame(frame);
}

runCycle();
if (!reduce) setInterval(runCycle, CYCLE_MS);
})();

02ストーリーグリッド — インパクトスコアを自分で求めてタイルの大きさを決めるグリッド

事例ごとの成果数値を今回のデータセットの最大値と比べて0〜1に正規化し、IMPACT_WEIGHT1のべき乗をかけてインパクトスコアを自分で求めます。スコアの段階ごとにgrid-column/grid-rowのspan・パディング・数字サイズを求め直し、固定クラスでは決め打ちしません。

ストーリーグリッド — インパクトスコアを自分で求めてタイルの大きさを決めるグリッド
新しいタブで開く

02 · ストーリーグリッド — インパクトスコアを自分で求めてタイルの大きさを決めるグリッド — 計測 累積面積 52.497% · 動いたフレーム 7/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

querySelectorAllclassList.addtransform-origin

IMPACT_WEIGHT1が正規化した値をタイルのspanに変える

applyは配列全体の最大値maxを求めてから各値を割り、tierForで段階を判定してタイルの見た目をまとめて書き換えます。

function apply(values) {
  var max = Math.max.apply(null, values);
  tiles.forEach(function (tile, i) {
    var value = values[i];
    var normalized = max > 0 ? value / max : 0;
    var weighted = Math.pow(normalized, IMPACT_WEIGHT);
    var tier = tierFor(weighted);
    tile.style.gridColumn = 'span ' + tier.col;
    tile.style.gridRow = 'span ' + tier.row;
    tile.dataset.pad = tier.pad;
    tile.dataset.font = tier.font;
    var valEl = tile.querySelector('.tileVal');
    if (valEl) valEl.textContent = String(value);
    if (!reduce) {
      tile.classList.remove('tile--pulse');
      void tile.offsetWidth;
      tile.classList.add('tile--pulse');
    }
  });
}

03メトリックハイライト — 以前・以後の比率を自分で割って求める強調カード

before・afterふたつの数値の改善幅をbeforeの値で割って比率を毎サイクル自分で求め、円周CIRC=2*Math.PI*RADIUSを計算してその比率をstroke-dashoffsetに逆算してゲージを満たします。正規化の上限はMAX_IMPROVEMENT.7で、ゲージの値はどこにもあらかじめ書いていません。

メトリックハイライト — 以前・以後の比率を自分で割って求める強調カード
新しいタブで開く

03 · メトリックハイライト — 以前・以後の比率を自分で割って求める強調カード — 計測 累積面積 2.328% · 動いたフレーム 17/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

stroke-dashoffsetrequestAnimationFramefont-variant-numeric

CIRCとMAX_IMPROVEMENT.7がゲージの角度を逆算する

computeRatioは改善方向をmetric.lowerIsBetterで分けてから比率を求め、applyGaugeがその比率をそのままstrokeDashoffsetに変換します。

function computeRatio(metric) {
  var delta = metric.lowerIsBetter ? (metric.before - metric.after) : (metric.after - metric.before);
  var improvement = delta / metric.before;
  return Math.max(0, Math.min(1, improvement / MAX_IMPROVEMENT));
}

function computePercent(metric) {
  var delta = metric.lowerIsBetter ? (metric.before - metric.after) : (metric.after - metric.before);
  return Math.round((delta / metric.before) * 100);
}

function applyGauge(ratio) {
  var offset = CIRC * (1 - ratio);
  fill.style.strokeDashoffset = String(offset);
}

function fmt(metric, value) {
  if (metric.unit === 'ms') return Math.round(value) + 'ms';
  return (Math.round(value * 10) / 10) + '%';
}

04引用ブロック — 文字数からフォントサイズを逆算する引用カード

引用文ごとに長さが違うため、カード内側の幅の2.6倍を目標幅として、そこに収まる最大の文字サイズをcanvasのmeasureTextで実際の描画幅を測りながら二分探索14回で逆算します。MIN_PX12からMAX_PX20の間をTOLERANCE1pxまで絞り込むので、固定pxの決め打ちではありません。

引用ブロック — 文字数からフォントサイズを逆算する引用カード
新しいタブで開く

04 · 引用ブロック — 文字数からフォントサイズを逆算する引用カード — 計測 累積面積 7.081% · 動いたフレーム 10/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

getContext('2d')measureTextclassList.add

二分探索14回でMIN_PX12〜MAX_PX20の間を絞り込む

solveFontSizeはlo・hiの中点midで実際の描画幅を測り、目標幅に収まっていればbestを更新して下限を上げる二分探索です。

function solveFontSize(text, targetWidth) {
  var lo = MIN_PX, hi = MAX_PX, best = MIN_PX;
  for (var i = 0; i < 14; i++) {
    var mid = (lo + hi) / 2;
    var w = widthAt(text, mid);
    if (w <= targetWidth - TOLERANCE) {
      best = mid;
      lo = mid;
    } else {
      hi = mid;
    }
  }
  return best;
}

function applyQuote(quote) {
  var targetWidth = textEl.clientWidth * 2.6; // 二行程度に収まる想定の文字幅予算
  var px = solveFontSize(quote.text, targetWidth);
  textEl.style.fontSize = px.toFixed(1) + 'px';
  textEl.textContent = quote.text;
  authorEl.textContent = quote.author;
}

05業種タブ — 切替のたびに業種別件数を数え直すタブ

タブをクリックして切り替えるたびに、その業種に属する事例数を合計TOTALで割ってパーセントを求め直しバッジを更新します。下線の位置・幅は選ばれたタブをgetBoundingClientRectで毎回実測してtranslateX/scaleXで動かすので、推測した固定座標は使いません。

業種タブ — 切替のたびに業種別件数を数え直すタブ
新しいタブで開く

05 · 業種タブ — 切替のたびに業種別件数を数え直すタブ — 計測 累積面積 2.14% · 動いたフレーム 9/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

getBoundingClientRectscaleXtranslateX

TOTALで割り直すたびに下線をgetBoundingClientRectで実測する

selectTabがaria-selectedを切り替えてからパーセントを求め直し、measureAndMoveが選ばれたボタンの実際の位置と幅で下線を移動させます。

function measureAndMove(idx) {
  var btn = buttons[idx];
  var wrapRect = tabsEl.getBoundingClientRect();
  var btnRect = btn.getBoundingClientRect();
  var x = btnRect.left - wrapRect.left;
  var w = btnRect.width;
  underlineEl.style.transform = 'translateX(' + x.toFixed(2) + 'px) scaleX(' + w.toFixed(2) + ')';
}

function selectTab(idx) {
  current = idx;
  buttons.forEach(function (b, i) {
    b.setAttribute('aria-selected', i === idx ? 'true' : 'false');
  });
  var tab = TABS[idx];
  var percent = Math.round((tab.count / TOTAL) * 100);
  countNumEl.textContent = String(tab.count);
  countLabelEl.textContent = '個 ' + tab.label + ' 件・全 ' + TOTAL + '件中 ' + percent + '%';
  measureAndMove(idx);
}

06ビデオカード — 露出割合から再生を、スクロール量から位置を求めるカード

カードがスクロールコンテナのビューポートに入っている割合をIntersectionObserver(51段階のthreshold)で実測して準備率を求め直し、その比率でプレビューフレームのインデックスを選んでキャンバスに描き直します。本物の動画ファイルはなく、フレームはシードを固定したmulberry32の疑似乱数で毎回同じ手続き的パターンを再現します。準備率がREADY_THRESHOLD.62を超えると再生ボタンが押せる状態に変わります。

ビデオカード — 露出割合から再生を、スクロール量から位置を求めるカード
新しいタブで開く

06 · ビデオカード — 露出割合から再生を、スクロール量から位置を求めるカード — 計測 累積面積 31.472% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

IntersectionObserverscrollTopgetContext('2d')

51段階thresholdのIntersectionObserverがREADY_THRESHOLD.62を判定する

updateは準備率からラベルの文言を書き換え、FRAME_COUNT12段階のうちどのフレームを描くかを決めてから再生ボタンの有効・無効を切り替えます。

function update(ratio) {
  var percent = Math.round(ratio * 100);
  readyLabel.textContent = '準備率 ' + percent + '%';
  var frameIndex = Math.min(FRAME_COUNT - 1, Math.floor(ratio * (FRAME_COUNT - 1)));
  if (frameIndex !== lastFrame) {
    lastFrame = frameIndex;
    drawFrame(frameIndex);
  }
  if (ratio >= READY_THRESHOLD) {
    playBtn.classList.add('playBtn--ready');
    playBtn.disabled = false;
  } else {
    playBtn.classList.remove('playBtn--ready');
    playBtn.disabled = true;
  }
}

07関連CTA — 共通タグ数から関連度を自分で求めるおすすめ

今見ている事例と他のカードのタグがいくつ重なるか(overlap)を毎回直接数えて関連度スコアとし、スコアの降順で並べ替えます。並び順の変化はFLIP(移動前の位置を記録 → DOMを更新 → 移動後の位置との差だけ逆補正して再生)でtransformだけを使って見せるため、レイアウト自体は一度も直接動かしません。

関連CTA — 共通タグ数から関連度を自分で求めるおすすめ
新しいタブで開く

07 · 関連CTA — 共通タグ数から関連度を自分で求めるおすすめ — 計測 累積面積 18.349% · 動いたフレーム 8/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

getBoundingClientRectclassList.addtranslate(

overlapを数え直してFLIPのdx/dyで並び替えを見せる

並べ替え後、firstRectsに記録しておいた移動前の座標と実際の位置lastとの差dx・dyを求め、その分だけ逆方向に置いてから通常のtransitionへ戻します。

CARDS.forEach(function (card) {
  var el = cardEls[card.id];
  var first = firstRects[card.id];
  var last = el.getBoundingClientRect();
  var dx = first.left - last.left;
  var dy = first.top - last.top;
  if (dx === 0 && dy === 0) return;
  el.style.transition = 'none';
  el.style.transform = 'translate(' + dx + 'px, ' + dy + 'px)';
  el.getBoundingClientRect();
  el.style.transition = '';
  requestAnimationFrame(function () {
    el.classList.add('card--flip');
    el.style.transform = '';
  });
  el.addEventListener('transitionend', function handler() {
    el.classList.remove('card--flip');
    el.removeEventListener('transitionend', handler);
  });
});

08ロゴバー — 数に比例して速度を求め直しループ時間を揃えるバー

ロゴ1セットの実際の描画幅を実測し、基準幅BASE_WIDTH560pxとの比率で一周の再生時間LOOP_SEC15秒を求め直すことで、ロゴの数や画面幅が変わっても流れる速度(1秒あたりのピクセル数)を一定に保ちます。MIN_SEC/MAX_SECの8〜40秒でduration自体も制限されます。

ロゴバー — 数に比例して速度を求め直しループ時間を揃えるバー
新しいタブで開く

08 · ロゴバー — 数に比例して速度を求め直しループ時間を揃えるバー — 計測 累積面積 3.005% · 動いたフレーム 23/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

getBoundingClientRecttranslateX--marquee-duration

halfWidthとBASE_WIDTH560pxの比率がLOOP_SECを求め直す

recomputeはdata-set="a"のロゴだけを対象に幅とマージンを合計してからdurationを求め、CSS変数--marquee-durationに反映します。

function recompute() {
  var setA = track.querySelectorAll('.logo[data-set="a"]');
  var halfWidth = 0;
  setA.forEach(function (el) {
    var rect = el.getBoundingClientRect();
    var style = getComputedStyle(el);
    halfWidth += rect.width + parseFloat(style.marginRight || '0');
  });
  var duration = LOOP_SEC * (halfWidth / BASE_WIDTH);
  duration = Math.max(MIN_SEC, Math.min(MAX_SEC, duration));
  track.style.setProperty('--marquee-duration', duration.toFixed(2) + 's');
  var pxPerSec = halfWidth / duration;
  speedNote.textContent = 'ロゴ ' + setA.length + '個・計算された一周 ' + duration.toFixed(1) + '秒・毎秒 ' + Math.round(pxPerSec) + 'px';
}

09事例フッター — これまで見た事例の平均を自分で求める要約バッジ

新しい閲覧が入るたびに平均を最初から割り直さず、累積合計sumと累積件数countだけを更新してrunning averageを計算します。EVENTS配列に固定した閲覧イベントを順番に回すだけなので、キャプチャごとに同じ数値の推移が再現されます。

事例フッター — これまで見た事例の平均を自分で求める要約バッジ
新しいタブで開く

09 · 事例フッター — これまで見た事例の平均を自分で求める要約バッジ — 計測 累積面積 0.79% · 動いたフレーム 8/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

classList.addsetIntervaltransform-origin

sumとcountだけを更新するrunning average

stepはidxが配列末尾に達すると先頭へ戻り、sum・countを積み上げてからaverageを割り直してバッジのテキストへ反映します。

function step() {
  if (idx >= EVENTS.length) idx = 0;
  var value = EVENTS[idx];
  sum += value;
  count += 1;
  idx += 1;

  var average = sum / count;

  countNum.textContent = String(count);
  avgNum.textContent = average.toFixed(1);
  feedNote.textContent = '最近: インパクト ' + value + '点を閲覧';

  if (!reduce) {
    countNum.classList.remove('statNum--bump');
    avgNum.classList.remove('statNum--bump');
    // リフローを強制し、同じクラスを再度付けてもアニメーションが再始動するようにする。
    void countNum.offsetWidth;
    countNum.classList.add('statNum--bump');
    avgNum.classList.add('statNum--bump');
  }
}

どこで使うセクションか — ケーススタディページを新しく作るチーム

ポートフォリオや営業資料に事例セクションを新しく追加するチームがこの9つのセクションを探す理由は、たいてい一つです。01 のように成果数値をカウントアップで見せたいけれど、桁が増えてもレイアウトが崩れない計算をどこから手をつければいいのか分からないからです。

複数業種の事例を1つのページにまとめる担当者は、05 のようにタブを切り替えるたびに業種別の件数を数え直す作業によく直面します。業種が増えたり事例が抜けたりしても、その数字が常に合っている必要があるのが次の問題です。

ページ最下部にこれまで見た事例の平均成果をまとめて見せたい担当者にとっては、09 の累積合計の計算がそのままその要約バッジの全てです。事例を1つ見るたびに全体を計算し直さず値だけを更新する方式が、ページの負荷を左右します。

数字が配置を変える場所 — インパクトスコア・引用の長さ・業種別件数

インパクトスコアがタイルのspanと余白を動かす

02ストーリーグリッドでは成果数値を正規化したweightedという1つの小数が、tierForを通じてgrid-columnのspan・grid-rowのspan・パディング・数字サイズという4つの見た目をまとめて動かします。数字を直接CSSに書くのではなく、段階の判定結果を渡している点がポイントです。

引用文の文字数がフォントサイズと行間を動かす

04引用ブロックでは引用文の文字数という外の数字が二分探索のtargetWidthとの比較を通じてpxという内の数字を動かし、そのpxが今度はカード全体のレイアウトを動かします。数字が数字を動かし、その数字がレイアウトを動かすという二段構えです。

業種別件数の合計がバッジの表示とタブの下線を動かす

05業種タブではTOTALという合計がpercentという比率に変わり、その比率がバッジの文言になります。件数が1件増えるごとに比率が均等に増えるのではなく合計で割った比率で増えるため、業種の数が変わってもパーセントの計算式そのものは変わりません。

reduced-motion込みで比べる3つの出し分け

紙のパンフレットに実績を並べるレイアウトと違い、この9種は同じ見た目のまま定数を1つ変えるだけで体験の重さが変わります。9種の実装はh4mdyx3hで開くzipにまとめてあり、vanillaフォルダには9項目それぞれのindex.htmlが、reactフォルダには同じ計算をコンポーネント化したtsxが入っています。

名前 値 感じ方
ヒーローカウントアップのイージング指数 01 EASE_POW 2 → 4 指数を2にすると数字がほぼ一定の速度で目標値まで上がり落ち着くがインパクトは弱く、4に上げると序盤は速く跳ね上がり終盤で急激に遅くなって最後の桁が着地する感じが強まるがめまいがしやすくなる
ストーリーグリッドのインパクト重み 02 IMPACT_WEIGHT .5 → 1.5 重みを.5に下げるとスコア差が緩やかになりタイルサイズが均等に分かれて安定するが、どの事例の成果が大きいか目立ちにくくなり、1.5に上げるとスコアが高い事例のタイルが大きく膨らんで視線を確実に引くが小さいタイルが過度に押しつぶされて見える
ロゴバーの一周時間 08 LOOP_SEC 15 → 30 一周を15秒に合わせるとロゴが速く流れて短い滞在でも複数のクライアントを見せられるが読むには忙しく、30秒に伸ばすとロゴ1つ1つをゆっくり読めるが全体を見るには長く留まる必要がある

prefers-reduced-motionをどう扱うか

9項目ともwindow.matchMedia('(prefers-reduced-motion: reduce)')の結果をreduceという変数に持ち、真であればカウントアップやマーキーのような演出だけを飛ばして最終値を即座に描画します。インパクトスコア・比率・関連度スコアのような計算そのものは省略しないため、動きだけが止まり結果は変わりません。

コピー&ペーストで動く理由

9項目とも配列定数・関数・クラス名を1つのindex.htmlの中だけで完結させ、外部のnpmパッケージやCDNは一切呼び出しません。フォルダを開いてブラウザに読み込ませるだけで、追加のビルド手順なしに同じ計算がそのまま動き出します。実績紹介ページを自作する際も、配列定数の中身だけ差し替えれば同じ計算の層をそのまま流用できます。

空の引用と0件の業種でどこから壊れるか

beforeの値が0のとき比率の計算がNaNになるとき

03のcomputeRatioはdeltaをmetric.beforeで割るため、成果指標のbeforeが将来0として渡されると比率がNaNになりゲージが描けなくなります。呼び出す前にbeforeが0でないことを確かめる一行を足しておくと安全です。

全業種の合計TOTALが0件になりパーセント表示がNaNになるとき

05のpercentはtab.countをTOTALで割った値をそのまま使うため、すべての業種が0件のデータセットが渡されると割り算そのものがNaNになりバッジの数字が表示できません。件数の合計が0の状態を先に弾いて、代わりに「事例準備中」のような文言へ切り替える分岐が必要です。

ロゴが1枚もないとき一周の時間が0に落ちて止まって見えるとき

08のdurationはhalfWidthとBASE_WIDTHの比率にLOOP_SECを掛けた値のため、ロゴが1枚も渡されずhalfWidthが0になるとdurationも0に近づき、マーキーが流れずに静止して見えます。MIN_SECの下限を通す前に対象のロゴ数を確かめておくと崩れません。

ケーススタディセクションを組み込む前によくある質問

業種タブのバッジの数字はどうやって決まりますか

タブをクリックするたびに、その業種に属する事例数を合計TOTALで割ってパーセントを求め直しています。業種Aが12件・全体43件なら28%という数字がその場で求まり、見た目の色分けとは別に毎回同じ式が動いています。

ビデオカードは本当の動画を再生しますか

いいえ。カードがビューポートに入っている割合をIntersectionObserverで実測して準備率を求め、その比率でシード固定の疑似乱数パターンをキャンバスに描いているだけで、本物の<video>はどこにもありません。準備率が閾値を超えると再生ボタンが押せる状態に変わり、押すと選ばれたフレームのプレビューが切り替わります。

ストーリーグリッドのタイルの大きさはどうやって計算していますか

シナリオが循環するたびに、各事例の成果数値を今回のデータセットの最大値と比べて0〜1に正規化し、べき乗の重みを掛けてインパクトスコアを自分で求めています。スコアの段階に応じてgrid-column/grid-rowのspanを求め直すため、データセットが変わるとタイルの大きさの並びごと変わります。

もっと読む

解凍パスワードを入力してください

パスワードはこの記事の本文の中にあります。読み進めると出てきます。