3 ポイント 投稿者 GN⁺ 2025-04-13 | 2件のコメント | WhatsAppで共有
  • SVGは単なるアイコン形式を超えて、maskpath、CSSアニメーションを組み合わせることで、線に沿って流れるワイヤー効果やTOCのハイライトを作れる
  • 中核となる実装は、lineまたはpathで作った線を直接見せるのではなく、マスク領域として使ってアニメーションするブロックの表示範囲を制限する方式
  • Animated Wiresはrectmask="url(#...)"を適用し、@keyframestranslateYを動かしつつ、linearGradientやCSS変数で視覚スタイルを拡張する
  • FumadocsのClerkスタイルTOCは、SSR互換性のためにアウトラインはサーバーでレンダリングし、アクティブな位置を示すthumbはブラウザーの位置情報を使ってクライアントでレンダリングする
  • SVG <path>d属性は自動生成された文字列ではなく命令の一覧なので、サーバーレンダリングされたTOCアウトラインと同じ形のマスク画像をクライアントで再構成できる

SVGマスクで作るAnimated Wires

  • サンプルコードは通常のHTMLではなく、JSXまたはReact構文を前提としている
  • 基本の線はSVGのlineまたはpathで作れる
    • 例ではviewBox="0 0 50 50"の中に縦のlineを配置している
  • 線を画面に直接描く代わりに、maskとして使って別の図形が見える範囲を制限する
    • rectmask="url(#line)"を適用し、maskの内部には白いlineを置く
  • 動きはrectにCSS animationを適用して作る
    • @keyframes to-downtranslateY(-10px)からtranslateY(50px)まで移動する
  • 視覚スタイルは背景線、より太いマスク線、linearGradient、CSS変数--heightを組み合わせて拡張する
    • @keyframes to-down-2calc(var(--height) * -1)から100%まで移動する
  • この種の似た効果の多くは、アニメーションするブロックをマスクで切り抜く方式を使っている
    • 一部のデザインはFigmaやほかのSVGエディターで作成できる
    • Unkeyのランディングページがこの方式の一例

FumadocsのClerkスタイルTOC

  • FumadocsにはClerkスタイルの**目次(TOC)**が実装されている
  • SSRと互換性を持たせるには、クライアントJavaScriptなしでサーバー側でTOCアウトラインをレンダリングする必要がある
    • サーバーでは要素の正確な位置はわからない
    • 実装ではabsolute配置を使い、アウトラインを複数のコンポーネントのようにレンダリングしてからつなぎ合わせる
  • アクティブ項目やビューポート内に見えているheadingに対応するアウトラインの一部はthumbとして表示される
    • thumbはアニメーションする必要があるため、単にアウトラインコンポーネントの色だけを変える方法では不十分
    • インタラクション対象であるthumbはクライアント側でレンダリングされる
  • ブラウザーから得た位置情報をもとに、クライアント側でマスクマップを構築する
    • このマスクマップの作成にはSVGを使う
    • SVG <path>d属性は命令の一覧であり、点をつないだ線をレンダリングできる
    • 関連ドキュメントはMDN Web DocsのSVG Pathsで確認できる
  • こうして作られたSVGは、サーバーで事前レンダリングされた元のTOCアウトラインと同じ形になる
  • Animated Wiresと同様に、CSS mask-imageにSVGをデータURLとして入れ、アニメーションするdivブロックをマスクしてハイライトされたthumbをレンダリングする
    • 内部のdivwidth: 1height: thumb.heighttransform: translateY(${thumb.top}px)transition: "all 500ms"backgroundColor: "white"のような値を使う
  • React.js実装はtoc-clerk.tsxのソースコードで確認できる

2件のコメント

 
ndrgrd 2025-04-14

かっこいいのは確かですが、今の項目を1つだけはっきり強調するほうが、目にはより留まりやすいですね。

 
GN⁺ 2025-04-13
Hacker News のコメント
  • 8年前の資料ではあるけれど、Sarah Drasner の有名な「SVG Can Do That?」という発表はいまでも多くの人の目を開かせてくれる
    その後 CSS はものすごく成熟したし、SVG 自体がそこまで変わったかはよく分からないけれど、とにかく強くおすすめする
    スライド: https://slides.com/sdrasner/svg-can-do-that
    動画: https://youtu.be/ADXX4fmWHbo?si=6YPZkopyEDc8PSte

    • その本もとても良いけれど、そこで勧められているツールが今でも有効かどうかはよく分からない
  • SVG ファイルでできる面白いことの一つは、インライン DTD のエンティティを使って、ファイル内の複数箇所で共有する定数を定義すること
    David Ellsworth の「Squares in Squares」ページにある SVG で、優れた例を見ることができる
    主要ブラウザでは問題ないが、Inkscape のような一部のツールは DTD をパースもせず、エンティティ展開もしない
    [0] https://kingbird.myphotos.cc/packing/squares_in_squares.html

    • ここで言う「エンティティ」は、実際には &ref のようなエンティティ参照で任意の構文内容を定義して再利用する SGML/XML の仕組みの名前
      SVG では図形やパスなどを defs の下に置いて id を付け、本文の SVG で再利用する方式で、リンク先のページも各 SVG 内でその方式を使っているように見える
      複数の図の間で四角形を共有しているわけではなく、それぞれ別々の DOM として入るから
      SVG の初期設計者たちが、なぜエンティティの仕組みを一時的に再実装する必要があると考えたのか気になる
      使用箇所でレンダリング属性を上書きできることと関係しているのかもしれないし、当時 SVG は W3C の XHTML/XML 移行の流れの中にあったので、ブラウザがエンティティ定義や文書プロローグ/DOCTYPE を無視するという前提もまだ確立されていなかったのだろう
    • 何か見落としているのかもしれないが、そのページで DTD を示すような !doctype!element が見つからない
      単に SVG の defsuse のことを言っているなら、それは DTD ではない
    • 既存の SVG の別の部分を取り出して、ページ内の別の場所で複製して使うこともできる
      https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/E...
    • ブラウザでは動作するかもしれないが、多くの SVG ツールはサービス拒否攻撃のリスクのため DTD を無視する
      例えば Billion laughs attack がある
      https://en.wikipedia.org/wiki/Billion_laughs_attack
    • そのページは 2022 年モデルの iPhone SE でレンダリングするのに、きっちり 5 秒ほどかかった
  • Nanda Syahrasyad の「A Deep Dive Into SVG Path Commands」は、SVG パスがどのように構成されるかを理解するのに本当に良い
    ほぼ 2 年前の記事だが、SVG に何ができるのか、そしてそれを正確にどうやるのかについて目を開かせてくれた
    [0] https://www.nan.fyi/svg-paths

  • SVG でこういう面白いことをするプロジェクトをやったことがある
    React で作り、複数の静的イラストにアニメーション要素を入れ、色は CMS で制御していた
    フロントエンドは API を呼び出して正しい色が入った SVG 画像を受け取り、アニメーションは SVG 要素を隠したり表示したりする形で処理していた
    例はここで見られる: https://web.archive.org/web/20221020133516im_/https://uncrow...

  • Macromedia Flash が本当に懐かしい
    Flash と SWF 形式のように、別途ダウンロードしなくても Flash Player さえあれば無数のインディーゲームやアニメ映画を楽しめる技術はなかった
    参入障壁も非常に低かった
    SVG にも SWF がやっていたことをすべて行える潜在力はあるが、Flash のようなエディタや、ActionScript のようなシーン/オブジェクトベースのコーディング方式がない
    ブラウザごとの癖もあるので、単純な SVG だけがどこでも正しく表示されると保証されている

    • 今でも Adobe Animate として残っており、HTML に書き出せる
      そもそも SVG と Flash を比較するのは、リンゴとオレンジの比較のように見える
      SVG 形式が Flash のしていたことをすべて直接行う必要はなく、ブラウザ内の他の技術に依存できる
    • WebAssembly が比較対象になり得ると思う
      例えば Unity、Unreal、Godot はブラウザ向けにかなり簡単にコンパイルできる
      問題は、こうしたアプリはかなり肥大化しがちで、普通は 1 桁 MB ではなく数十 MB 規模になりやすいこと
    • これを再び作るスタートアップの機会がありそう
  • 複雑なアニメーション SVG は動かしてみると楽しいが、SMIL の奥深くに入ると、Safari が浮動小数点数の前の 0 が一つ抜けているだけでスマホを固まらせたり、妙なことが起きたりする

  • JavaScript で SVG を動的かつ創造的に作っていて、仕事を探しているなら DM してもよい

  • 線の濃度を許容する SVG 拡張があるのか気になる
    ペンを上げ下げできるプロッターがあり、SVG ファイルで駆動される
    手書きでよくやるように、線を描いている途中でペンを下げられるとよい
    ちなみに Evil Mad Scientist Labs の Axidraw で、素晴らしい装置だし、作っている人たちも素敵だ

    • 通常の SVG ファイル内にユーザー定義の指示を保存し、リーダー側で解釈するのはかなり簡単
      例えば多目的レーザーカッター/プロッターを使っているが、不透明度はレーザー出力、線幅は移動速度、緑チャンネルは反復回数、青チャンネルは Z 軸の高さ、赤チャンネルはペン下げやレーザーオフなどに使っている
    • おそらくそういうものは G-code で処理する方がよさそう
      この種の作業をここでやってきている
      https://github.com/WillAdams/gcodepreview
  • 自分でアイコンやロゴを作ってみるまでは、SVG に**変換(transform)**が入っているのはいつも変だと思っていた
    曲線をきちんと合わせるのは難しい
    2 つ目のロゴを仕上げてみたら平坦すぎて見えたので、10° 傾けたくなり、そのすべての線と曲線を書き直すことを考えると、回転の方がずっと良い選択に見えた
    幸いテキストの横に置くと変だったので、カーニングが合って見えるように角度をさらに何度か変えることになった

  • 最近、趣味で小さなゲームを作り、レンダリングには主に CSS アニメーション SVG タイルを使った: https://pipeline-panic.vercel.app/