MOTION PALETTE
← すべてのデモ

Chart Pulse

HeroSVG / GSAP

フルスクリーンで開く ↗

枠の中でスクロール・クリックして動きを試せます。端末指定は実寸表示です。幅が足りない場合は横にスクロールできます。

再現プロンプト

架空のリアルタイム収益分析SaaS PULSEGRIDの1ページ。折れ線がストロークドローで描かれ面が満ち、末端が一定周期で脈動更新し続け、棒グラフは一度だけオーバーシュートして伸びる。数値は常に静止表示。 配色・構成・動きの数値をまとめた指示書です。 お使いのAIに貼り、素材やお店の情報を伝えて実装してください。仕上がりは利用するAIと素材によって変わります。

Build a single self-contained HTML file (inline CSS/JS) for "PULSEGRID", a fictional real-time revenue-intelligence SaaS whose whole brand idea is "data that keeps breathing": every chart draws itself, fills itself, then keeps quietly updating on a fixed cadence, as if reading a live ledger. No number anywhere on the page ever animates — MRR, churn, prices and bar values are always static text; every bit of motion is pushed into the chart geometry, never into the digits. May use a CDN script for gsap (with the ScrollTrigger plugin). The page scrolls with the normal window (no inner scroll container needed for the standalone output).

## Art direction
Palette: page background #0A1116, panel background #111C22, hairline borders rgba(38,198,218,0.18), primary text #EAF3F5, muted text #8CA3AA, single accent cyan #26C6DA used for every line, glow, bar and CTA — no other hue. Monospace (ui-monospace / "SF Mono" / Menlo) for eyebrows, chart titles and plan names; a bold system sans (font-weight 800) for headings and KPI values. A fixed 60px top nav (translucent, blurred, 1px bottom hairline) shows "PULSEGRID" with a "LIVE REVENUE INTELLIGENCE" sub-label, links to Metrics / Growth / Plans, and a "Start Free Trial" pill. A 2px top progress bar fills cyan as the page scrolls (ScrollTrigger scrub 0.3, trigger = full document height).

## Deterministic dummy data (must match exactly — no Math.random in any render/animation loop)
All series are generated once, at load time, by a seeded PRNG (mulberry32: a += 0x6D2B79F5 with two xorshift-multiply rounds, output normalized to 0..1) so the same seed always reproduces the same numbers. A shared "random walk" builder takes (seed, count, base, amp, drift) and repeats: v += (rand()-0.42)*amp + drift, clamped to 0, pushing v each step. Root seed constant: 20260711 (SEED_BASE); every series uses SEED_BASE + a fixed small offset (e.g. +1 for the hero, +2 for ARR, +3..+6 for the four KPI sparklines, +7 for the footer strip) so all data is reproducible and documented in code. Series: hero MRR — 14 weekly points, base 82000, amp 5200, drift 2100; ARR growth — 8 quarterly points, base 940000, amp 42000, drift 61000, labeled Q1 '24 through Q4 '25; four KPI sparklines (10 points each) behind "MRR" ($128,420, +12.4%), "Active Accounts" (4,812, +6.1%), "Net Churn" (1.8%, -0.4pt), "Avg. Deal Size" ($2,340, +3.2%) — all delta/value text is static, never tweened or counted up. Revenue-by-channel bars (static, not a time series): Self-Serve $482K, Sales-Assisted $701K, Partners $214K, Marketplace $138K, Enterprise $612K, bar height = value / max(values) * 176px (BAR_MAX_PX). For the "live" tail refresh described below, use a second pure function of elapsed seconds t (no randomness at all): liveSignal(t) = sin(t*0.9)*0.6 + sin(t*2.3+1.4)*0.3 + sin(t*5.1+0.6)*0.12.

## The line-chart engine (must match exactly — reused by every chart)
Every line/area chart is one instance of the same renderer against a fixed viewBox: hero 640x260 (padding 22, stroke 3), growth trend 680x280 (padding 26, stroke 3), KPI sparklines 168x56 (padding 6, stroke 2), footer strip 800x60 (padding 4, stroke 2). Points are mapped linearly: x = padding + i/(n-1) * (w - 2*padding), y = padding + innerH - (v-min)/(max-min) * innerH. The line path is built as a sequence of quadratic curves where each segment's control point is the current point and its endpoint is the midpoint to the next point (a cheap smoothing trick, no external library) — "M x0,y0" then repeated "Q xi,yi mx,my", ending with a final "L" to the true last point. The area path reuses the same line string then closes down to the baseline (h - padding) and back to the first point's x, forming a filled polygon; it is filled with a vertical gradient from rgba(38,198,218,0.55) at the top to rgba(38,198,218,0.02) at the bottom.

Two-stage draw (the page's core signature — exact seconds): stage 1 draws the stroke using the classic SVG technique — set stroke-dasharray to the path's own getTotalLength(), set stroke-dashoffset to that same length, then tween strokeDashoffset to 0 over 1.4s (LINE_DRAW_S) with ease power2.inOut. Stage 2 fills the area: the area path starts at scaleY(0) with CSS transform-box: fill-box and transform-origin: 50% 100% (so it grows upward from its own baseline), tweening to scaleY(1) over 0.9s (AREA_FILL_S) with ease power1.out, with its start delayed to LINE_DRAW_S - 0.15s (AREA_FILL_OVERLAP_S) after stage 1 begins — the fill visibly starts rising 0.15s before the stroke finishes drawing, so the hand-off reads as one continuous gesture instead of two separate animations.

Living pulse (exact seconds): the chart's rightmost point carries two CSS-driven infinite loops on a 2.4s cadence (PULSE_PERIOD_S) — a filled circle that scales 1 -> 1.35 -> 1 (keyframes cp-breathe, ease-in-out) and a concentric ring that scales 1 -> 2.6 while fading opacity 0.55 -> 0 (keyframes cp-ping, ease-out) — both driven purely by CSS animation-duration, not JS. In parallel, a JS interval fires every 2.4s (starting once the two-stage draw finishes) and re-solves the last 6 points (TAIL_POINTS) of the series: for each of those points, target y = its original mapped y + liveSignal(elapsed-seconds-since-load + index*0.35) * 10px (TAIL_AMP_PX); every older point's target is simply its original y (it settles back to baseline). A tween on a plain {t:0->1} proxy object, duration 0.6s (TAIL_MORPH_S) ease sine.inOut, lerps every visible point between its last displayed position and this new target every animation frame, rebuilding both the line and area "d" strings and repositioning the pulse circles each tick — so the most recent history gently resettles while the newest edge keeps moving, forever, without ever touching a number.

Hover crosshair (the page's pointer interaction, present on the hero and growth charts): on pointermove over the chart, compute the nearest data index from the cursor's x position, then move a vertical guide line and a highlighted dot to that point and show a small tooltip (absolutely positioned by percentage of the chart's own box) reading "{label} · {formatted value}" — snapping to whichever point is nearest, never tweening the number. Opacity fades in/out over 0.15s. Hidden entirely on pointerleave.

## Section 1: Hero
Eyebrow "PULSEGRID // LIVE REVENUE INTELLIGENCE", H1 "Watch your revenue breathe.", one line of subcopy about transactions streaming live, a "START FREE TRIAL" CTA plus a small "● LIVE" badge whose dot breathes on the same 2.4s loop as the charts. Below: a bordered chart panel titled "MRR — LAST 90 DAYS" holding the 640x260 hero chart, auto-playing its two-stage draw 0.3s after mount (not scroll-gated, since it is already in view), with the hover crosshair active.

## Section 2: Live Metrics
Heading "Numbers that hold still. Charts that don't." above four KPI cards (MRR, Active Accounts, Net Churn, Avg. Deal Size) — each shows its static label, static value, static delta, then its own 168x56 sparkline beneath, two-stage-drawing and then living-pulsing once the card scrolls to "top 88%" of the viewport (ScrollTrigger, one-shot).

## Section 3: Revenue by Channel
Heading "Where the revenue actually comes from." above five bars (Self-Serve, Sales-Assisted, Partners, Marketplace, Enterprise) — plain HTML/CSS bars (not SVG), each pre-set to its final pixel height and animated via scaleY 0 -> 1 with transform-origin 50% 100%, duration 0.85s (BAR_GROW_S), ease back.out(1.7) — this ease overshoots the target scale once before settling, never oscillating a second time — staggered 0.09s (BAR_STAGGER_S) per bar, triggered once when the section reaches "top 80%". Each bar's static dollar value and channel name sit below it as plain text.

## Section 4: Growth Trend
Eyebrow "GROWTH // 8-QUARTER TREND", heading "The trend line no one has to defend.", one sentence inviting the reader to hover. The 680x280 growth chart (ARR across 8 quarters, labeled Q1 '24 - Q4 '25) plays its two-stage draw once the section reaches "top 78%" of the viewport, then keeps living-pulsing; its hover crosshair works identically to the hero's.

## Section 5: Plans
Heading "Pick a cadence, not just a tier." above three pricing cards — Starter ($0/forever: 1 live workspace, 3 connected sources, 7-day history), Growth ($89/month, marked "MOST COMMON": 10 live workspaces, unlimited sources, 2-year history), Scale ($310/month: unlimited workspaces, realtime API access, full audit log). Each card also shows a tiny 3-bar "capacity" chip (heights proportional to a 0-3 scale, max 34px, one set of values per plan) using the exact same elastic-bar animation as Section 3, triggered independently per card at "top 85%".

## Footer
Heading "Start streaming your data.", a "START FREE TRIAL" mailto CTA, then a full-width thin decorative 800x60 "heartbeat" strip using the identical line-chart engine (drawn once the footer reaches "top 85%", then living-pulsing forever) as a closing echo of the hero chart, followed by a footer row with "© 2026 PULSEGRID" and a contact email.

## Scroll animations
Every piece of copy on the page (eyebrows, headings, body copy, CTAs, KPI text, plan text, footer row) shares one "focus-in" reveal instead of a translateY fade: opacity 0 -> 1 and filter blur(4px) -> blur(0px) (TEXT_REVEAL_BLUR), duration 0.6s (TEXT_REVEAL_S), ease power2.out, triggered per element at ScrollTrigger start "top 88%" with toggleActions "play none none reverse", staggered 0.08s (TEXT_REVEAL_STAGGER) per line within each section's group. onLeaveBack reverses over 0.3s. No element anywhere uses a plain y+opacity fade, no numbered "01/02/03" list styling appears, and no value on the page ever counts up or digit-rolls — every number is set once as static text and stays that way; only the surrounding chart geometry moves.

## Performance & accessibility
Chart "d" (path) attributes are only rebuilt inside the tail-morph tween's onUpdate (throttled to one rAF-driven tween per 2.4s per chart, 0.6s duration) — never recomputed on a global per-frame loop. Each chart's path length is measured once via getTotalLength() right after its initial "d" attribute is set. Bars and line charts alike are only ever driven by ScrollTrigger "once: true" triggers plus the recurring pulse interval, so nothing continues animating off-screen unnecessarily once revealed. Under prefers-reduced-motion: the two-stage draw and elastic-bar grow both snap instantly to their final state, the CSS breathe/ping loops are removed entirely, the living tail-refresh interval never starts, and every text reveal is set to its resting state immediately instead of scrubbing on scroll; the hover crosshair remains available since it only moves in direct response to explicit pointer input. All interactive elements (nav links, CTAs) are real buttons/links with visible hover and focus-visible states against the #0A1116 background, and every KPI/bar/price value remains fully readable as plain static text regardless of animation support.

## Action flow and content

Implement the following local planning experience for the primary CTA, in the visual language of the page. Use a real button opening a labelled modal dialog. Choosing a pricing card must preselect that exact plan. A navigation link may move to another section; a planning CTA must lead to its review flow.

Use this content for the dialog, including the option details and notes:

{
  "slug": "chart-pulse",
  "brand": "PULSEGRID",
  "accent": "#277265",
  "title": "Choose a dashboard starting point",
  "intro": "Compare a plan and record what you need to understand about your data.",
  "facts": [
    [
      "Getting started",
      "Define the data source, business question and intended readers."
    ],
    [
      "Sample data",
      "Every chart on this page is illustrative."
    ],
    [
      "Trial scope",
      "This local plan does not create an account or connect to a data source."
    ]
  ],
  "groups": [
    {
      "label": "Plan",
      "options": [
        {
          "title": "Starter",
          "detail": "Start with the free plan shown on the page · $0."
        },
        {
          "title": "Growth",
          "detail": "The growth plan shown on the page · $89 per month."
        },
        {
          "title": "Scale",
          "detail": "The team plan shown on the page · $310 per month."
        }
      ]
    }
  ],
  "brief": "Describe the data you would use and the question this dashboard should answer.",
  "notes": [
    "Displayed prices are examples; billing, access and integration requirements need confirmation for a real service."
  ]
}

- Explain before input that this is a fictional brand sample: choices can be reviewed and saved, with no external submission, booking, payment or registration. Use each brand's language. Do not launch a mail client or present an installer for a fictional product.
- Give every option group a legend, inputs explicit labels and errors linked descriptions. Validate options against the allowed values, requested dates as actual dates from today onward, and free text as 10–2,000 trimmed characters. Blank spaces alone must fail. Tracking accepts the sample reference TG-2048 only.
- Focus the first invalid field and preserve every entered value. On success, show the selected option WITH its full detail, requested date or brief, relevant facts and notes. An edit action returns to the preserved form. Do not claim a real reservation, purchase or account has succeeded.
- Save the complete review as UTF-8 text. A browser download request is not proof of a file being written. On download failure, retain the full text in a labelled, selectable textarea and offer retry. Do not show a false success state.
- Constrain modal content to the viewport with internal scrolling. Support keyboard and touch, trap focus while open, close on Escape and restore focus to the exact initiating control. Keep these operations available with motion disabled.
- If a separate project-contact CTA is present, let it collect a project brief and review it locally; a product selection CTA must retain the product choice. Verify both flows independently.