ホームページ >ウェブフロントエンド >CSSチュートリアル >% CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します

% CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します

Linda Hamilton
Linda Hamiltonオリジナル
2025-01-18 06:10:09390ブラウズ

これは、「CSS で 32 ビット API 応答データを取得する」の直接のフォローアップです

CSS では、16 ビットの応答データが固有の幅と固有の高さの両方に配置され、(JavaScript なしで) API 応答データをまったく取得できなかった状況から大幅に改善されました...

しかし、それを理解してから数日で、私の心は次の方向に傾きました。
たった 2 回ではなく、16 ビット 32 回だったら、もっと楽しいでしょう。

Gif recording of a harsh terminal app setting several integer values to an array of variables one at a time

抽出のために 512 ビットを SVG にパックする

私は寝る前に瞑想していて、別のインスピレーションを受けた考えに襲われました -

「画像ドキュメント自体独自の固有サイズをアニメーション化できるとしたらどうなるでしょうか?"

インスピレーションを受けた思考の後の通常の一連の気づきは、それぞれがどのように実現できるかについての理解を示しました...そのようなイメージタイプが存在するかどうかを理解する必要があっただけです。

私は携帯電話を手に取り、知っているすべてのアニメーション画像形式を検索して、その形式に対応できるものがあるかどうかを確認しました。 svgwebpapnggif奇妙なビデオ形式かもしれません?何も見つかりませんでした。

朝、私の中の何かがSVG を掘り続けようと言った。

埋め込み CSS、メディア クエリ、使用定義、さらに使用定義を試し、多数の SVG アニメーション ドキュメントに飛び込み、それらをだまそうとし、他のアイデアやアニメーション関連のプロパティを読んでみましたが、何もできませんでした。高さまたは幅を設定します。

しかし、最後のリンクを見て私は考えさせられました...

...viewBox についてはどうですか?他にも取り組むべきハードルはいくつかありますが...あれはアニメーション化できますか?

うわー
それは!!
^^

ソリューション空間の整理

問題は、ルート svg 要素に幅と高さの属性を設定せずに、その svg を擬似的なコンテンツとして使用しようとすると、0px x 0px でレンダリングされることです。これは、ベクター ドキュメントであり、固有のサイズ。

そこで、preserveAspectRatio を検索して追加しました...まだ 0x0...しかし、CSS で幅を 10px に固定し、viewBox の保持されたアスペクト比によって高さを決定させました (これは、 SVG に埋め込まれたアニメーション) ああ、そして...それを含む HTML 要素が予想される高さまで成長しました。

:3

フレームが 1 つしかない場合、元の 32 ビットが半分にカットされます。抽出できるのは 1 つの次元のみで、もう 1 つの次元は静的であるためです。

しかし!さて、私の 2 番目の次元は 時間 で、最初の次元は時間に左右されるので、十分すぎるほどのデータがあります。

なんとも刺激的ですね!

私は SVG でアニメーションを制御する方法についてできる限りのことを学び、サーバー側スクリプトを作成して最初のアニメーション SVG を生成しました。

<?php header('Content-type: image/svg+xml');

  $data = array(
    400,
    450,
    150,
    20,
    175
  );

  $datalen = count($data);

  $viewBoxXYWidth = '0 0 10 ';

  $frames = array_map(function ($val, $index) use ($viewBoxXYWidth) {
      return $viewBoxXYWidth . ((string) ($val));
  }, $data, range(1, $datalen));

  $dur = $datalen * 0.33; // total seconds

  $keytimeStep = 1 / ($datalen); // uniform portion per frame

  $keytimes = implode("; ", array_map(function ($index) use ($keytimeStep) {
      return ($index * $keytimeStep);
  }, range(0, $datalen - 1)));

  $values = implode("; ", $frames); 

  echo '<svg viewBox="0 0 10 100" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg">
    <animate attributename="viewBox" dur="' . $dur . 's" fill="freeze" begin="0.1s;" values="' . $values . '" keytimes="' . $keytimes . '" repeatcount="indefinite" calcmode="discrete"></animate>
  ';
?>

(なぜ php なのか?! - 私はすでに何年も料金を払っているサーバーを持っていたので、すぐに php を実行できるように設定していました。そして、JavaScript とノードを知って素晴らしい生計を立てているにもかかわらず、そうですね。詳細を知らなくても、関数、演算子、構文をすべて調べて、できることがわかっていることを進めていくのは、楽しいこともあります。笑)

次に、前の記事から最初の % CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します をフォークして、CSS が --vars に応答し、SVG の動作に合わせてサイズが変化する様子を見てみましょう。

確認しました!サイズの変更を読み取ることができます。前の記事と同様に、最終的には、この Tan(atan2()) 手法の代わりにビュー タイムライン測定手法を使用することになります。

CPU がクックされるため、抽出が完了したらコンテンツから削除する必要があります。

概念的に、1D 時間を手続き的に抽出する方法

上記のデモは、それ自体ではあまり役に立ちません。高さが存在する場合は必ずそのコピーを報告しますが、それを保存する必要があります...そして、順序が分からず信頼できない場合、16 ビット値の束が何の役に立つのでしょうか?

CPU ハックを使用して CSS に値を蓄積し、以前の値を保持するだけでなく、どの --var が受信値を更新するかを数学的に決定できることはわかっているので、CSS については特に心配しません。一般に、時間をかけて 1D を抽出するにはどうすればよいでしょうか?

センチネルの価値観が助けになります!

データパケット自体を16ビットに制限したい場合でも、使用する測定領域のサイズは16ビットに制限する必要はありません。それで、そこにセンチネルも詰め込むことができます。 css-api-fetch には、65535 (16 ビットの上限) をはるかに超える 99999 までの値を処理する機能が付属しています。

では、何を知る必要があるのでしょうか?

どのような問題が発生する可能性がありますか?

データ内の 2 つの値が連続して同じである場合、それが 2 つの異なるパケットであることを知るために中断が必要です。 512 ビットを目指すことはすでに決めているので、SVG のアニメーションには最大 32 個の 16 ビット データ フレームがあり、その間にセンチネル フレームが必要です...

CPU が重いと感じられる場合、SVG アニメーションが個別のステップを完全にスキップしているように見える場合があります。つまり、自分がどの段階にいるのかを常に知る何らかの方法が必要です。したがって、単一の「データ フレーム間」センチネルではなく、データ インデックス (CSS nth-* セレクターのように 1 に基づく) をセンチネル値として使用して、そのインデックスのデータを表示する個別のステップの前に独自の個別のステップを作成しましょう。

センチネルインデックス ->データ ->センチネルインデックス ->データ ...

これにより、いつループするか、おそらくセンチネル 1 に到達したときも知ることができます。

しかし、別のデータ フレームにスキップして、誤って間違ったスロットに記録してしまったではないことをどうやって知ることができるのでしょうか?

ループさせて正しくなるまで続けます。データが正しいかどうかを知る最良の方法はチェックサムです。したがって、別のデータ フレームと、その値のセンチネルが必要です。

チェックサムアルゴリズムの作成

css-bin-bits を使用してすべてのデータの XOR を実行することもできますが、これは非常に重いので、他の場所では必要ありません。CSS で簡単に実行できる代替手段に落ち着きましょう。

数学的には、16 ビット値を取得し、それを 256 (整数の整数) で割って、その 16 ビット値を再度 256 で法的に取得すると、上位バイトと下位バイトが得られます。これらの 8 ビット値を合計すると、9 ビットになります。これは合理的なチェックサムのアプローチのように思えますが、ここに戻りましょう。

最終チェックサムが 16 ビットである限り、チェックサムを計算するために 16 ビット範囲に留まる必要はありません。したがって、すべて (最大) を合計しましょう。 32 の値。

ただし、フレームのスキップによるストレージへの誤った書き込みには注意する必要があるので、偶数のインデックス値を 2 回追加して、順序のようなものを作りましょう。

16 ビット値の 32 倍とさらに 16 倍の合計は、約 22 ビットになります。以前の考えに戻って各側の 11 ビットを分割してモジュール化し、それらを加算して、チェックサム応答として 12 ビットを返します。

合理的だと思われます...完全にエラーを防止できるわけではありませんが、SVG はいくつかの手順をスキップして、同じチェックサムを生成できるように台無しにする必要があります...いずれにせよ、データも送り返しましょう長さをチェックサムの最後のステップとして追加するだけで、それもチェックサムに含めます。最大データ長 (処理したい 16 ビット値の数) はわずか 32 であるため、長さの値を 12 ビットに追加しても 16 ビットを超えることはありません。やったー!

ネタバレ: これは私がやったことですですが、CSS が 21 ビットあたりで損失が多くなったので、分割して同じアルゴリズムを効果的に実行しましたが、一度に小さい単位で実行しました。サーバー側は説明どおりに alg を使用します。

技術的には、これまで説明したセットアップでは、アニメーション内での順序は関係ありません。各センチネルがアニメーション内での順序は関係ありません。 >データ

.

もう 1 つ、データ長の値を応答の最初に置き、そのセンチネルも追加しましょう (残りのデータと同様に、SVG アニメーション内のセンチネルは値の前にあります)。

それは 34 人のセンチネル です。 SVG viewBox の高さを 0 にすることはできません。CSS では、内部的にデータを表さないように 0 を許可すると利点があるため、35 個のセンチネルがあり、0 個は意図的に使用されていないとします。

すべてのデータ フレームは、値に 35 が追加されて SVG に埋め込まれます。長さとチェックサムのデータ値もビューボックスの値に 35 を追加します。センチネルを表す SVG アニメーションの viewBox の高さは 0 ~ 34 (0 はスキップ) の値を持ち、それぞれが SVG アニメーションの次のフレームが何を表すかを正確に示します。

CSS 側では、生の測定値が 34 より大きいかどうかを確認するだけです。これはデータなので、そこから 35 を引きます。35 未満の場合はセンチネルです。

A meme picture of Charlie Day from It's Always Sunny in Philadelphia with a crazed look standing in front of a board covered in paper with red lines connecting them hectically

CSS を使用して 512 ビットを抽出し始める

詳しく説明したように SVG アニメーションを生成する PHP 側の作業を完了した後、この抽出プロセス用の CSS を開始する具体的な方法を考えました。

これが PHP コードです!
<?php header('Content-type: image/svg+xml');

  $data = array(
    400,
    450,
    150,
    20,
    175
  );

  $datalen = count($data);

  $viewBoxXYWidth = '0 0 10 ';

  $frames = array_map(function ($val, $index) use ($viewBoxXYWidth) {
      return $viewBoxXYWidth . ((string) ($val));
  }, $data, range(1, $datalen));

  $dur = $datalen * 0.33; // total seconds

  $keytimeStep = 1 / ($datalen); // uniform portion per frame

  $keytimes = implode("; ", array_map(function ($index) use ($keytimeStep) {
      return ($index * $keytimeStep);
  }, range(0, $datalen - 1)));

  $values = implode("; ", $frames); 

  echo '<svg viewBox="0 0 10 100" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg">
    <animate attributename="viewBox" dur="' . $dur . 's" fill="freeze" begin="0.1s;" values="' . $values . '" keytimes="' . $keytimes . '" repeatcount="indefinite" calcmode="discrete"></animate>
  ';
?>

CSS でこれを実現する方法はいくつかありますが、最近の仕様追加によりさらに多くの方法が追加される可能性があります。

私の最初のアプローチは概念的に最も簡単です。すべてのデータに対してビュータイムラインを使用し、同じことを何度も繰り返します。それは機能していましたが、私はそれがどれほどひどいものであるかに不満を感じながら、進行中にうめき声を上げました。このまま続けると、:root 上に 40 個近くのアニメーションが作成されることになります。

それで私は寝ました。

目が覚めたとき、私は起きたばかりの、または瞑想したばかりのようなざわめきを感じながら微笑みながら窓の外を眺めながら数分間横たわっていましたが、それから頭の中にさまざまな考えが流れ込んできました。私は寝返りをしてノートと一番近くにあったペンを手に取り、ベッドに起き上がり、わずか 6 つの CSS アニメーションでデータを抽出するアルゴリズムを書き留め始めました。

my chicken scratch handwriting on a single piece of lined notebook paper with arrows pointing to a couple of nested boxes detailing the method described below

文字通り紙の上で解決します。これはまさにの実装方法です。

私は立ち上がってコンピューターに向かい、前の仕事を無視して新しい % CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します を開きました。

そこでチキン スクラッチ内に示されている 4 つの HTML 要素を設定し、CSS パネルにそれらに対応する 4 つの空のクラス セレクターの周囲のメモを埋め込みました。今は :root にはありませんが、これに依存するものはすべてその中に置くことができます。

メモが紙からコピーされ、% CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します でより具体的な詳細が書き込まれるまで、機能は 1 つも追加されませんでした。

完了したら、メモを読み、そこに書かれていることを実行し、最終的な動作結果に至るまで実行を開始しました。

(256 ビットでテストするつもりだったので、「35」の代わりに「20」と書きました)

その仕組みについて詳しく説明します。ビュー タイムラインとタイムライン スコープにより、表面がアニメーションして「穴」に吸い込まれていく様子を想像できれば、クラインの壷のような形でデータが流入するように設定できます。狭い上部から下部まで戻ることができます。再び表面上で、ダム層を通ってサイズと複雑さを増してから、ブラックホールを通って高次の意識 (:root) にループバックします。

ほとんどが垂直方向に周期的です (ほとんどが水平方向に周期的または静的に周期的であるというよりは)

CSS を使用して 512 ビットを抽出する

少し調整してより明確にしたメモ:

256 テスト -> 512 ファイナル

そして、内部にプレゼンテーション ノードを追加しました。これは、アルゴリズムの実行中に内部も表示できるため、非常に優れています。

ただし、実装とプレゼンテーションのノイズをすべて除いた最終的なメモがここにあります。これは、すべてがどのように機能するかを正確に説明しています。

記事にこれほど多くの詳細が外部に埋め込まれているのは良い形式ではないかもしれませんが、各チャンクを分割してどのように実装されているかを示します。

メインコントローラー

この構造の上部には 4 つのタイムライン値とそのアニメーションがあります。それでは、これらを入れてみましょう。

これにより可能になるデータ フローの重要な部分は、DOM の奥深くにネストされたデータをホスト (タイムライン スコープ) に持ち上げる機能を提供することです。これは効率的ではないため、これを行う頻度を制限したいと考えています。登録された各プロパティとそのアニメーションは、単一のデータを垂直方向にホストできます。データの値は、構造内のどこか深いところにある要素のインラインまたはブロック ビューの位置によって決まります。その部分については後ほど説明します。

(データ フローのより明確な図については、上に埋め込まれたループの例を参照してください)

ここで取り上げる 4 つのデータは次のとおりです:

--xfl-cpu-phase - これは、現在実行されている CPU ハックのフェーズを示す 0 ~ 4 の数値です。 (CPU ハックの 1 つの「フレーム」は 4 ~ 5 個の CSS レンダリング フレームであり、フェーズの 1 つのループが CPU ハックを「ティック」します) これについては、この記事の後半でより具体的に説明します。

--xfl-raw-data - SVG がアニメーション サイクル内に存在する場合、SVG の高さをホストします。私たちの生データ。前に述べたように、この値が 35 未満の場合、SVG アニメーションのこの個別のステップはセンチネル値です。 34 より大きい場合、SVG アニメーションのこの個別のステップは 16 ビット値 35 であり、前のセンチネルが示したものに対応します。

--xfl-data-type - これは最新のセンチネル値です。この値は、次のセンチネルに遭遇するまで変わりません。 --xfl-raw-data を設定してからこの値を設定するまでに 1 CSS フレームの遅延があります。

--xfl-data-value - これは生の値から 35 を引いた後の現在のデータ値です。シーケンスのこのステップにまだ達していない場合は 0 です。 --xfl-data-type を設定してからこの値を設定するまでに 1 CSS フレームの遅延があります。

また、機能のみを備え、プロセスが不完全な間アニメーション化された SVG のみをロードする条件で svg-animation-current-state-reporter をプリエンプティブにラップしました。 (つまり、すべての内部要素がメモリから削除され、終了時に重いアニメーション SVG がレンダリングから削除されます)

キーフレーム値は、そのデータの最大値から 0 まで変化します。これらが逆である理由は後で説明します。Uno Reverse カードの画像を探してください。

CPUエクスフィルタレーター

次に、CPU ハックの基本的な定型文をセットアップします

CPU ハックのボイラープレートは、変数名のパターンに従ってキャプチャとホイストのアニメーションを設定するだけです。

水平方向に (時間の経過とともに) 循環させたい 1 つの整数 --xfl\1 がある場合、それを登録し、次のようにキャプチャおよびホイスト アニメーションを設定します。

<?php header('Content-type: image/svg+xml');

  $data = array(
    400,
    450,
    150,
    20,
    175
  );

  $datalen = count($data);

  $viewBoxXYWidth = '0 0 10 ';

  $frames = array_map(function ($val, $index) use ($viewBoxXYWidth) {
      return $viewBoxXYWidth . ((string) ($val));
  }, $data, range(1, $datalen));

  $dur = $datalen * 0.33; // total seconds

  $keytimeStep = 1 / ($datalen); // uniform portion per frame

  $keytimes = implode("; ", array_map(function ($index) use ($keytimeStep) {
      return ($index * $keytimeStep);
  }, range(0, $datalen - 1)));

  $values = implode("; ", $frames); 

  echo '<svg viewBox="0 0 10 100" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg">
    <animate attributename="viewBox" dur="' . $dur . 's" fill="freeze" begin="0.1s;" values="' . $values . '" keytimes="' . $keytimes . '" repeatcount="indefinite" calcmode="discrete"></animate>
  ';
?>

次に、2 つの CPU アニメーションがホストされている .cpu-exfiltrator 要素で周期的な割り当てを完了します。現時点では、値の 1 つだけに対してそれを実行します:

<?php header('Content-type: image/svg+xml');

  $data = array(
    400,
    450,
    150,
    20,
    175
  );

  $datalen = count($data);

  $viewBoxXYWidth = '0 0 10 ';

  // add 35 to all the values so we can use 0 to 34 for sentinels. 0 = CSS-side sentinel, 1-32 = data frames, 33 = length, 34 = checksum
  $frames = array_map(function ($val, $index) use ($viewBoxXYWidth) {
      return ($viewBoxXYWidth . ((string) $index) . '; ' . $viewBoxXYWidth . ((string) ($val + 35)));
  }, $data, range(1, $datalen)); // 1 up to 32 = indicator that next frame is the value(+35) for that index(1-based)

  // no matter how many are in the array, '33' indicates the next frame is data length, which is used in the checksum too
  array_unshift($frames, $viewBoxXYWidth . '33; ' . $viewBoxXYWidth . ((string) ($datalen + 35))); // + 35 b/c data
  // unshift so the length is (hopefully) the first value read and a sense of progress can be reported

  $fullsum = 0;

  for ($x = 0; $x <= ($datalen - 1); $x++) {
    // double the odd ones so there's some semblance of order accounted for
    // the odd ones with 0 based index is the even ones on the CSS side
    $fullsum += ($data[$x] + (($x & 1) * $data[$x]));
  }

  $checksum = floor($fullsum / 2048) + ($fullsum % 2048) + $datalen + 35; // + 35 because it's data

  // no matter how many are in the array, '34' indicates the next frame is checksum
  array_push($frames, $viewBoxXYWidth . '34; ' . $viewBoxXYWidth . $checksum);

  $actualNumItems = count($frames) * 2;

  $dur = $actualNumItems * 0.33; // total seconds

  $keytimeStep = 1 / ($actualNumItems); // uniform portion per frame

  $keytimes = implode("; ", array_map(function ($index) use ($keytimeStep) {
      return ($index * $keytimeStep);
  }, range(0, $actualNumItems - 1)));

  $values = implode("; ", $frames); 

  echo '<svg viewBox="0 0 10 100" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg">
    <animate attributename="viewBox" dur="' . $dur . 's" fill="freeze" begin="0.1s;" values="' . $values . '" keytimes="' . $keytimes . '" repeatcount="indefinite" calcmode="discrete"></animate>
  ';
?>

Chrome では、両方のアニメーションが同時に実行されていない限り、静的に循環しません (初期値になります)。これは、数値プロパティを設定して一時停止したアニメーションを最適化することによる素晴らしい副作用です。

最後に、CPU ハックの新しい自動バージョンを使用しているため (元のハックのようにフェーズを循環させるために :hover する必要はありません)、--xfl-cpu-phase var に配線します。前から (ここでは親要素でホストされているため、スタイル クエリを使用してそれに応答できます)、アニメーションの再生状態を制御します。

また、--cpu-next-phase を出力します。これは後で上部に持ち上げられ、ビュー位置とタイムライン スコープを使用して --xfl-cpu-phase の次の値を設定します。

SVG アニメーションの測定が次の --xfl-data-type で正常にロックされるまで CPU ハックを一時停止しておくフェーズを追加しました

<?php header('Content-type: image/svg+xml');

  $data = array(
    400,
    450,
    150,
    20,
    175
  );

  $datalen = count($data);

  $viewBoxXYWidth = '0 0 10 ';

  $frames = array_map(function ($val, $index) use ($viewBoxXYWidth) {
      return $viewBoxXYWidth . ((string) ($val));
  }, $data, range(1, $datalen));

  $dur = $datalen * 0.33; // total seconds

  $keytimeStep = 1 / ($datalen); // uniform portion per frame

  $keytimes = implode("; ", array_map(function ($index) use ($keytimeStep) {
      return ($index * $keytimeStep);
  }, range(0, $datalen - 1)));

  $values = implode("; ", $frames); 

  echo '<svg viewBox="0 0 10 100" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg">
    <animate attributename="viewBox" dur="' . $dur . 's" fill="freeze" begin="0.1s;" values="' . $values . '" keytimes="' . $keytimes . '" repeatcount="indefinite" calcmode="discrete"></animate>
  ';
?>

(現状では、データ型は常に 0 なので、次のフェーズが接続されると、これはすでに CPU ハックをループします。データ型センチネルを取得すると、それが完了するまでループしません。 0センチネルで意図的にクリアしました)

後で、データがすべて整うまで CPU フェーズ 1 が開始されないように、上記の条件も追加します。これにより、データ タイプ (センチネル) がロックインされてからデータ値 (生 - 35) がロックされるまでの間、CPU ハックをキャプチャ フェーズのままにすることが保証されます。つまり、エイブラハム・ヒックスが言うように、「準備ができている」のです。

先に進み、SVG アニメーションがレポートする予定の 32 個の値すべてに加えて、チェックサムと長さを登録します。

--xfl\1 から --xfl\32 までの登録は大きなブロックであり、CPU アニメーションも定型的なものであるため、これらすべてをハック設定の一番下に移動して、今後は無視されるようにします。

自動CPUハッキング

これにより、次の CPU フェーズが --xfl-cpu-phase 値に配線されます

<?php header('Content-type: image/svg+xml');

  $data = array(
    400,
    450,
    150,
    20,
    175
  );

  $datalen = count($data);

  $viewBoxXYWidth = '0 0 10 ';

  // add 35 to all the values so we can use 0 to 34 for sentinels. 0 = CSS-side sentinel, 1-32 = data frames, 33 = length, 34 = checksum
  $frames = array_map(function ($val, $index) use ($viewBoxXYWidth) {
      return ($viewBoxXYWidth . ((string) $index) . '; ' . $viewBoxXYWidth . ((string) ($val + 35)));
  }, $data, range(1, $datalen)); // 1 up to 32 = indicator that next frame is the value(+35) for that index(1-based)

  // no matter how many are in the array, '33' indicates the next frame is data length, which is used in the checksum too
  array_unshift($frames, $viewBoxXYWidth . '33; ' . $viewBoxXYWidth . ((string) ($datalen + 35))); // + 35 b/c data
  // unshift so the length is (hopefully) the first value read and a sense of progress can be reported

  $fullsum = 0;

  for ($x = 0; $x <= ($datalen - 1); $x++) {
    // double the odd ones so there's some semblance of order accounted for
    // the odd ones with 0 based index is the even ones on the CSS side
    $fullsum += ($data[$x] + (($x & 1) * $data[$x]));
  }

  $checksum = floor($fullsum / 2048) + ($fullsum % 2048) + $datalen + 35; // + 35 because it's data

  // no matter how many are in the array, '34' indicates the next frame is checksum
  array_push($frames, $viewBoxXYWidth . '34; ' . $viewBoxXYWidth . $checksum);

  $actualNumItems = count($frames) * 2;

  $dur = $actualNumItems * 0.33; // total seconds

  $keytimeStep = 1 / ($actualNumItems); // uniform portion per frame

  $keytimes = implode("; ", array_map(function ($index) use ($keytimeStep) {
      return ($index * $keytimeStep);
  }, range(0, $actualNumItems - 1)));

  $values = implode("; ", $frames); 

  echo '<svg viewBox="0 0 10 100" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg">
    <animate attributename="viewBox" dur="' . $dur . 's" fill="freeze" begin="0.1s;" values="' . $values . '" keytimes="' . $keytimes . '" repeatcount="indefinite" calcmode="discrete"></animate>
  ';
?>

ここには、要素をスクロール コンテナにして画面外に置くための CSS ボイラープレートがあります。重要な部分は次のとおりです:

ビュータイムライン: --xfl-cpu-phase inline;

これは、この疑似要素の右端が幅 100 ピクセルの親のどこに位置するかを示し、それを左から 0 から 4 に移動するアニメーションに「進行状況」として接続します...つまり、25 ピクセルは 25% 完了しています。 25% が 0 ~ 4 の場合に 1 にマッピングされます。

picture of two 'reverse' cards from Uno 画像は twitter につながる Google 検索から引用

技術的には、アニメーションは 4 から 0 であり、技術的には、ビューが右に進むにつれて擬似の右端から測定されます。したがって、幅 25 ピクセルの疑似は、幅 100 ピクセルの親スクロールの右から 75% にあり、75% が 4 と 0 の間にある場合、値 1 にマップされます。

逆逆計算を認知的に処理せず、アニメーションの最大値が 4 であるため、最終結果が 0 から 4 への単純な進行であることを受け入れると、理解しやすくなります (ここでもアニメーション が開始することは無視されます) 4)。

データの準備ができるまで CPU をフェーズ 0 に保持する準備完了状態も書きましょう。このメモはデモの 64 行目にあります:

データ準備完了 = データ型 > 0 && raw フレーム データ - 35 === データ値

<?php header('Content-type: image/svg+xml');

  $data = array(
    400,
    450,
    150,
    20,
    175
  );

  $datalen = count($data);

  $viewBoxXYWidth = '0 0 10 ';

  $frames = array_map(function ($val, $index) use ($viewBoxXYWidth) {
      return $viewBoxXYWidth . ((string) ($val));
  }, $data, range(1, $datalen));

  $dur = $datalen * 0.33; // total seconds

  $keytimeStep = 1 / ($datalen); // uniform portion per frame

  $keytimes = implode("; ", array_map(function ($index) use ($keytimeStep) {
      return ($index * $keytimeStep);
  }, range(0, $datalen - 1)));

  $values = implode("; ", $frames); 

  echo '<svg viewBox="0 0 10 100" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg">
    <animate attributename="viewBox" dur="' . $dur . 's" fill="freeze" begin="0.1s;" values="' . $values . '" keytimes="' . $keytimes . '" repeatcount="indefinite" calcmode="discrete"></animate>
  ';
?>

待ってください、=== は CSS ですか?

これらは現在ではかなり時代遅れであり、clamp() がベースラインになる前に書かれたものなので、今日は別の方法で実行するつもりですが、私は常にこの古いコードペンを開いて、必要なときに数値コンパレータを何も考えずにコピー&ペーストしています。これらを更新して説明するのは良い記事になるでしょうが、それまではここで説明します: https://codepen.io/propjockey/pen/YzZMNaz

SVG アニメーションの読み取り

これは、最初は CPU Exfiltrator セクションと 非常に 似ています。これは同じ手法であり、ここから DOM を経由してホストされている場所 (スコープ) までデータを測定して移動するためです。

最初に設定した基本要素の最後の 3 つの値を測定して報告します。

::before で SVG をレンダリングし、アニメーション化された SVG の高さの測定値であるブロック ビューの位置を使用して --xfl-raw-data を設定します。 (幅を 10px に固定することに注意してください)

::after で、--xfl-data-type インライン (センチネル値 0 ~ 34) と --xfl-data-value ブロック (16 ビット値) を設定します。

親は、SVG をレンダリングし (少なくとも 10 ピクセル)、センチネル値 (0 ~ 34) の測定値を正確に提供するのに十分な幅が必要です。

親も、16 ビット値 (35) を測定できる十分な高さである必要があります。最初のステップで最大値を 100k に設定したので、必要な値より約 30% 大きくても、そのままそれを使用します。

そして、スクロールバーが発生しないように、画面外の上と左に移動します。

したがって、

.svg-animation-current-state-reporter


を取得します

<?php header('Content-type: image/svg+xml');

  $data = array(
    400,
    450,
    150,
    20,
    175
  );

  $datalen = count($data);

  $viewBoxXYWidth = '0 0 10 ';

  // add 35 to all the values so we can use 0 to 34 for sentinels. 0 = CSS-side sentinel, 1-32 = data frames, 33 = length, 34 = checksum
  $frames = array_map(function ($val, $index) use ($viewBoxXYWidth) {
      return ($viewBoxXYWidth . ((string) $index) . '; ' . $viewBoxXYWidth . ((string) ($val + 35)));
  }, $data, range(1, $datalen)); // 1 up to 32 = indicator that next frame is the value(+35) for that index(1-based)

  // no matter how many are in the array, '33' indicates the next frame is data length, which is used in the checksum too
  array_unshift($frames, $viewBoxXYWidth . '33; ' . $viewBoxXYWidth . ((string) ($datalen + 35))); // + 35 b/c data
  // unshift so the length is (hopefully) the first value read and a sense of progress can be reported

  $fullsum = 0;

  for ($x = 0; $x <= ($datalen - 1); $x++) {
    // double the odd ones so there's some semblance of order accounted for
    // the odd ones with 0 based index is the even ones on the CSS side
    $fullsum += ($data[$x] + (($x & 1) * $data[$x]));
  }

  $checksum = floor($fullsum / 2048) + ($fullsum % 2048) + $datalen + 35; // + 35 because it's data

  // no matter how many are in the array, '34' indicates the next frame is checksum
  array_push($frames, $viewBoxXYWidth . '34; ' . $viewBoxXYWidth . $checksum);

  $actualNumItems = count($frames) * 2;

  $dur = $actualNumItems * 0.33; // total seconds

  $keytimeStep = 1 / ($actualNumItems); // uniform portion per frame

  $keytimes = implode("; ", array_map(function ($index) use ($keytimeStep) {
      return ($index * $keytimeStep);
  }, range(0, $actualNumItems - 1)));

  $values = implode("; ", $frames); 

  echo '<svg viewBox="0 0 10 100" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg">
    <animate attributename="viewBox" dur="' . $dur . 's" fill="freeze" begin="0.1s;" values="' . $values . '" keytimes="' . $keytimes . '" repeatcount="indefinite" calcmode="discrete"></animate>
  ';
?>

とそれ以前は

@keyframes capture {
  0%, 100% {
    --xfl\1-captured: var(--xfl\1);
  }
}

@keyframes hoist {
  0%, 100% {
    --xfl\1-hoist: var(--xfl\1-captured, 0);
  }
}

そして::afterは
を取得します

  --xfl\1: calc(
    var(--xfl\1-hoist, 0) + 1
  );

基本的に、これらの後の値の記憶媒体は、親スクロール コンテナに対する 1 ピクセルの正方形の疑似の表示位置です。擬似自体は 1x1 であり、対応する値が 0 の場合に 0 を報告するようにするため、左と上の計算で 1px を減算します。

これはすべて、以前に実行したものと非常に似ています。

注に示されているように、これらの値を計算する方法にはいくつかの複雑さがあります。

  @container style(--xfl-cpu-phase: 4) {
    animation-play-state: paused, paused;
    --cpu-next-phase: calc(
      min(1, var(--xfl-data-type)) * 4
    );
  }

これを解決する方法を理解するための鍵は、コンパレータの値が 0 または 1 に設定されていることです。true の場合は 1、false の場合は 0 です。次に、それに何らかの値を掛けます。 false の場合、結果は 0 のままですが、それ以外の場合は、任意の値になります。

アナ チューダーが、このアイデアがどのように機能するかをここで詳しく説明します

次に、2 番目の値について異なる比較または反対の比較を使用してその比較を 2 回実行し、それらを加算すると (コンパレータの最大 1 つが 1 であることを確認します)、そのうちの 2 つの加算は単に「else」と言っていることになります。もし"。

準備ができていない場合 * 古い値を使用します。そうでない場合
準備ができている場合 * この新しい値を使用します

これは、タイプがすでに報告された後、SVG アニメーションの値に対する離散ステップの期間中、センチネル値を保持する方法です。

これを実装する CSS コードは、ここの 191 行目、一番下の方に配置した --xfl\... プロパティ登録の大きなブロックのすぐ上から始まります
@property --xfl\1 { 構文: "";初期値: 0;継承: true; }
...
追加のメモが含まれています:

特定の CSS --var 値の設定 (アドレス指定された割り当て)

今触れたロジックは、--xfl\1、2、32 のすべての値に使用する概念とまったく同じです。

<?php header('Content-type: image/svg+xml');

  $data = array(
    400,
    450,
    150,
    20,
    175
  );

  $datalen = count($data);

  $viewBoxXYWidth = '0 0 10 ';

  $frames = array_map(function ($val, $index) use ($viewBoxXYWidth) {
      return $viewBoxXYWidth . ((string) ($val));
  }, $data, range(1, $datalen));

  $dur = $datalen * 0.33; // total seconds

  $keytimeStep = 1 / ($datalen); // uniform portion per frame

  $keytimes = implode("; ", array_map(function ($index) use ($keytimeStep) {
      return ($index * $keytimeStep);
  }, range(0, $datalen - 1)));

  $values = implode("; ", $frames); 

  echo '<svg viewBox="0 0 10 100" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg">
    <animate attributename="viewBox" dur="' . $dur . 's" fill="freeze" begin="0.1s;" values="' . $values . '" keytimes="' . $keytimes . '" repeatcount="indefinite" calcmode="discrete"></animate>
  ';
?>

--xfl-data-type が 1 に等しいかのように --xfl-set\1 を読み取り、暗黙の else 0 を指定して --xfl-data-is-ready を使用します

--xfl-data-is-ready は、フェーズ 1 に切り替わるまでフェーズ 0 に保持するフラグとして以前に確立されました。

つまり、条件は && ロジックです。合格するには両方のフラグが 1 でなければなりません。

次に、--xfl-set\1 が --xfl-data-value (現在の SVG アニメーション値) を使用するかのように --xfl\1 の読み取りを続けます。そうでない場合は --xfl-set\1 を使用します -- xfl\1-hoist (CPU ハックが --xfl1 に対して保持していた以前の値)

これは非常に反復的であり、この流出の残りの部分のほぼ全体を説明しています。

最後のステップでは、基本的な calc() と mod() の計算を実行して、前に説明したようにチェックサムを構築し、計算されたチェックサム === SVG アニメーションに埋め込まれたチェックサムを CPU ハックに追加して、いつであるかを知ることができます。完了。まったく同じです。

それでは、いよいよです。 :)

プレゼンテーション: CSS アニメーション SVG 抽出ハック

このハックのすべての部分を要素ごとに 1 つの値で示したかったため、このプレゼンテーションは不快なほど重いです。 HTML は 2000 行以上、CSS は 400 行以上あります。さらに、css-bin-bits を使用して各レジスタをバイナリなどに変換しています。

(リアルタイムで実行されることを確認するには、コードペン フレームの右下にある [再実行] をクリックします。)

JavaScript は使用できません!


連絡先を開きますか?

これが素晴らしいと思われ、さらに詳しく知りたい場合は、ぜひご連絡ください。ご質問はいつでも喜んでお答えいたします。

% CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します % CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します DEV Blog % CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します % CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します
% CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します % CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します DEV Blog % CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します % CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します

?@JaneOri.% CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出します

?@Jane0ri

以上が% CSS: アニメーション SVG に埋め込まれたサーバー生成データのビットを取得して抽出しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。