برنامه نویسی

100٪ CSS: واکشی و استخراج 512 بیت از داده های تولید شده توسط سرور که در یک SVG متحرک جاسازی شده اند.

این یک پیگیری مستقیم برای دریافت داده های پاسخ API 32 بیتی در CSS است

در CSS، 16 bits داده‌های پاسخ، که هم در عرض ذاتی و هم در ارتفاع ذاتی قرار می‌گیرند، به دلیل عدم امکان دریافت داده‌های پاسخ API (بدون جاوا اسکریپت) پیشرفت بزرگی بود…

با این حال، در روزهای پس از اینکه متوجه شدم، ذهنم به یک جهت متمایل شد:
اگر بود خیلی سرگرم کننده تر می شد 16 bits 32 بار به جای فقط دو بار

ضبط گیف از یک برنامه ترمینال خشن که چندین مقدار صحیح را در یک آرایه از متغیرها تنظیم می کند.

بسته بندی 512 بیت در یک SVG برای Exfiltration

قبل از خواب داشتم مدیتیشن می‌کردم و یک فکر الهام‌گرفته دیگر تحت تأثیر قرار گرفتم –

«اگر برای سند تصویر امکان پذیر بود چه می شد خود برای متحرک کردن آن خود اندازه ذاتی؟”

زنجیره‌ی معمول تحقق‌ها پس از یک فکر الهام‌آمیز، هرکدام با درک چگونگی انجام آن چشمک می‌زند… من فقط باید بفهمم که آیا چنین نوع تصویری وجود دارد یا خیر.

تلفنم را برداشتم و تمام فرمت‌های تصویر متحرکی را که می‌شناختم جستجو کردم و دیدم که آیا هیچ کدام از آنها قادر به انجام آن هستند یا خیر. svg، webp، apng، gif، شاید فرمت های ویدیویی عجیب و غریب? من نتونستم هیچ کدوم رو پیدا کنم

صبح، چیزی در من گفت به حفاری در SVG ادامه دهید.

من CSS تعبیه‌شده، پرسش‌های رسانه‌ای، استفاده از دف‌ها، استفاده از دف‌های بیشتر، غواصی در اسناد متحرک SVG متعدد، تلاش برای فریب دادن آن‌ها، و خواندن سایر ایده‌ها و ویژگی‌های مرتبط با انیمیشن را امتحان کردم – هیچ چیز نمی‌توانست به من اجازه تعیین ارتفاع یا عرض

اما همین لینک آخر مرا به فکر انداخت…

… چه خبر viewBox? من می خواهم با موانع دیگری مقابله کنم اما … است که امکان متحرک سازی وجود دارد؟

vvv
این است!!
^^^

مرتب کردن فضای راه حل

حالا مشکل اینجاست که اگر تنظیم نکنید width و height صفات روی ریشه svg عنصر سپس سعی کنید از svg as استفاده کنید content روی یک pseudo، ارائه می دهد 0px x 0px زیرا یک سند برداری است و دیگر اندازه ذاتی ندارد.

بنابراین من جستجو کردم و saveAspectRatio را به آن اضافه کردم… هنوز 0x0… اما سپس در CSS، عرض را به آن پین کردم 10px و اجازه دهید نسبت ابعاد حفظ شود viewBox ارتفاع را تعیین کنید (که می توانم آن را با یک انیمیشن تعبیه شده در SVG تغییر دهم) aaand… عنصر html حاوی آن به ارتفاع مورد انتظار رشد کرد.

:3

اگر فقط یک فریم وجود داشت، این 32 بیت اصلی من را گرفت و آن را از وسط نصف کرد. از آنجایی که فقط یک بعد را می توان استخراج کرد در حالی که بعد دیگر ساکن است.

اما! حالا بعد دوم من بود زمان و اولین مورد در اختیار زمان است، بنابراین داده‌های بیش از اندازه کافی برای داشتن وجود دارد.

چقدر هیجان انگیز!

من تمام آنچه می توانستم در مورد نحوه کنترل انیمیشن در SVGها یاد گرفتم و یک اسکریپت سمت سرور برای تولید اولین SVG متحرک خود ایجاد کردم:


  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 '
    . $dur . 's"
      fill="freeze"
      begin="0.1s;"
      values="' . $values . '" 
      keytimes="' . $keytimes . '"
      repeatCount="indefinite"
      calcMode="discrete"
    />
  ';
?>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

(چرا php؟! – چون قبلاً سروری داشتم که سال‌ها برایش پول پرداخت می‌کردم، راه‌اندازی کردم تا php از گیت خارج شود… و حتی با وجود اینکه با دانستن جاوا اسکریپت و نود واقعاً خوب درآمد خوبی کسب کرده‌ام، گاهی اوقات سرگرم کننده است برای جستجوی تک تک عملکردها، عملگرها و نحوها برای پیشرفت در چیزی که شما را می شناسید می تواند بدون دانستن جزئیات انجام دهید روده بر شدن از خنده)

حالا بیایید اولین CodePen خود را از مقاله قبلی جدا کنیم تا ببینیم که CSS به –vars پاسخ می دهد و اندازه آن را تغییر می دهد، همانطور که SVG در کنار آن علامت زده می شود:

تایید شد! ما می تواند تغییر سایز را بخوانید مانند مقاله قبلی، در پایان، از آن استفاده خواهد کرد view-timeline تکنیک اندازه گیری به جای این تکنیک tan(atan2()).

CPU من را می پزد، بنابراین ما می خواهیم آن را از آن حذف کنیم content زمانی که اکسفیلتراسیون کامل شد

از نظر مفهومی، چگونه به صورت رویه ای 1D + زمان را استخراج کنیم

نسخه ی نمایشی بالا به تنهایی مفید نیست. هر زمان که هست یک کپی از ارتفاع را گزارش می‌کند، اما باید آن را ذخیره کنیم… و اگر شما سفارش را نمی‌دانید و نمی‌توانید به آن اعتماد کنید، دسته‌ای از مقادیر 16 بیتی چه فایده‌ای دارند؟

می‌دانم که می‌توانم با هک CPU مقادیری را در CSS جمع‌آوری کنم و به‌طور ریاضی تعیین کنم که کدام –var مقادیر ورودی را به‌جای حفظ مقدار قبلی خود به‌روزرسانی می‌کند، بنابراین به‌طور خاص نگران CSS نخواهم بود. به طور کلی چگونه می توانیم 1D را در طول زمان استخراج کنیم؟

ارزش های نگهبان برای نجات!

اندازه ناحیه اندازه گیری مورد استفاده ما نباید به 16 بیت محدود شود حتی اگر بخواهم خود بسته های داده را به 16 بیت محدود کنم. بنابراین ما می توانیم تعدادی نگهبان را نیز در آنجا ببندیم. css-api-fetch کشتی هایی با توانایی مدیریت مقادیر تا 99999، که به خوبی بالاتر است 65535 (سقف 16 بیتی).

پس چه چیزی باید بدانیم؟

ممکن است به چه مشکلاتی برسیم؟

اگر دو مقدار در داده های ما پشت سر هم یکسان هستند، ما به یک وقفه نیاز داریم تا بدانیم دو بسته مجزا هستند. من قبلاً تصمیم گرفتم که 512 بیت را هدف گذاری کنیم، بنابراین ما به انیمیشن SVG نیاز داریم که حداکثر 32 فریم داده 16 بیتی داشته باشد، با فریم های نگهبان در بین …

اگر CPU احساس سنگینی می کند، ممکن است به نظر برسد که انیمیشن SVG به طور کامل مراحل گسسته را رد می کند. این بدان معناست که ما به راهی نیاز داریم تا همیشه بدانیم در چه مرحله ای قرار داریم. بنابراین به جای یک نگهبان منفرد «بین فریم‌های داده»، بیایید از شاخص داده (بر اساس 1 مانند انتخابگرهای CSS nth-*) به عنوان مقدار نگهبان استفاده کنیم، و آن را قبل از مرحله گسسته که داده‌های آن شاخص را نشان می‌دهد، مرحله گسسته خود را بسازیم.

Sentinel index -> data -> sentinel index -> data ...

این به ما امکان می‌دهد بفهمیم که چه زمانی حلقه می‌شود، به طور بالقوه وقتی به نگهبان ضربه می‌زنیم 1.

اما از کجا بفهمیم که به یک قاب داده متفاوت پرش نکرده است و تصادفاً ما آن را در شکاف اشتباهی ضبط کنیم?

ما باید به آن اجازه دهیم حلقه و ادامه بده تا درست بشه، و بهترین راه برای دانستن اینکه داده ها درست هستند یا خیر، چک جمع است! بنابراین ما به یک قاب داده دیگر و یک نگهبان برای آن مقدار نیاز داریم.

ایجاد الگوریتم Checksum

میتونستم استفاده کنم css-bin-bits به XOR تمام داده ها، اما بسیار سنگین است و در هیچ جای دیگری مورد نیاز نیست – بیایید به جایگزینی بپردازیم که انجام آن در CSS ساده است.

از نظر ریاضی، اگر یک مقدار 16 بیتی بگیرید، آن را بر 256 (از طبقه به عدد صحیح) تقسیم کنید و مقدار 16 بیتی را مجدداً مدول روی 256 بگیرید، بایت های بالا و پایین را دریافت می کنید. این مقادیر 8 بیتی را با هم اضافه کنید و به 9 بیت می رسید. به نظر می رسد که این یک رویکرد جمع کنترلی معقول است، اما اجازه دهید به این دایره برگردیم.

ما مجبور نیستیم در محدوده 16 بیت بمانیم محاسبه کنید چک جمع تا زمانی که جمع نهایی 16 بیت است، پس بیایید همه (تا) 32 مقدار را جمع کنیم.

با این حال، باید مراقب ذخیره سازی نادرست نوشتن به دلیل فریم های نادیده گرفته شده باشیم، بنابراین بیایید مقادیر شاخص زوج را اضافه کنیم. دو بار بنابراین وجود دارد ظاهری از نظم.

آن مجموع، 16 bit values، 32 times، به علاوه یک اضافی 16 times، در مورد است 22 bits. تقسیم و ماژول 11 bits در هر طرف به فکر قبلی بچرخید، سپس آن‌ها را با هم اضافه کنید و بدهید 12 bits به عنوان پاسخ جمع چک ما.

منطقی به نظر می رسد… این کاملاً اثبات کننده خطا نیست، اما SVG باید چندین مرحله را رد کند تا آن را به هم بزند، به نحوی که شاید همین چک جمع را در حال حاضر ایجاد کند… در هر صورت، بیایید آن را نیز برگردانیم. data length و آن را نیز در چک‌سام قرار دهید، فقط با اضافه کردن آن به عنوان آخرین مرحله از چک‌سوم ما. حداکثر طول داده (تعداد مقادیر 16 بیتی که می خواهیم مدیریت کنیم) فقط است 32، بنابراین اضافه کردن مقدار طول به 12 بیت به هیچ وجه ما را به بیش از 16 بیت فشار نمی دهد. آری

اسپویلر: این است کاری که من انجام دادم اما CSS حدود 21 بیت از دست رفت، بنابراین آن را تقسیم کردم و به طور موثر همان الگوریتم را انجام دادم اما در تکه های کوچکتر در یک زمان. سمت سرور دقیقاً همانطور که توضیح داده شد از alg استفاده می کند.

از نظر فنی، با تنظیماتی که توضیح دادیم، مهم نیست که ترتیب آن چه باشد انیمیشن تا زمانی که هر نگهبان به شما بگوید که فریم بعدی قرار است در کدام شاخص باشد داده ها.

یک چیز دیگر، بیایید قرار دهیم data length value ابتدا در پاسخ و یک نگهبان برای آن نیز اضافه کنید (سنتینل در انیمیشن SVG قبل از مقدار، مانند بقیه داده ها).

یعنی 34 نگهبان. SVG viewBox ارتفاع نمی تواند باشد 0 و CSS از این اجازه سود خواهد برد 0 برای نشان دادن هیچ داده ای در داخل، بنابراین فرض کنید داریم 35 نگهبان با 0 عمدا استفاده نشده

همه فریم های داده اکنون با SVG جاسازی می شوند 35 به ارزش آنها افزوده است. Length و checksum مقادیر داده نیز دریافت می شود 35 به مقدار Viewbox اضافه شد. viewBox ارتفاعات در انیمیشن SVG که نشان دهنده نگهبانان است دارای مقادیر خواهد بود 0 تا 34 (با رد شدن از 0) و هر کدام دقیقاً به ما می گویند که فریم بعدی در انیمیشن SVG چه چیزی را نشان می دهد.

سمت CSS، ما فقط بررسی می کنیم که آیا اندازه گیری خام بزرگتر از 34 است، این است data پس کم کن 35 از آن، اگر کمتر از 35، این یک است sentinel.

تصویری از چارلی روز از فیلم همیشه آفتابی در فیلادلفیا با ظاهری دیوانه در مقابل تخته ای پوشیده شده از کاغذ با خطوط قرمز که آنها را به شدت به هم متصل می کند ایستاده است.

شروع به استخراج 512 بیت با CSS

بعد از اینکه قسمت PHP را برای تولید انیمیشن SVG به صورت جزئی به پایان رساندم، به روش‌های خاصی برای شروع CSS برای این فرآیند exfiltration فکر کردم.

کد پی اچ پی اینجاست!


  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 '
    . $dur . 's"
      fill="freeze"
      begin="0.1s;"
      values="' . $values . '" 
      keytimes="' . $keytimes . '"
      repeatCount="indefinite"
      calcMode="discrete"
    />
  ';
?>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

چند راه برای انجام این کار در CSS وجود دارد و به طور بالقوه راه های دیگری با اضافه شدن مشخصات اخیر وجود دارد.

اولین رویکرد من از نظر مفهومی ساده‌ترین روش است – استفاده از یک نمایش زمان برای هر قطعه داده و انجام یک کار مشابه بارها و بارها. کار می‌کرد، اما من از پیشرفتم ناله می‌کردم که از شدت ناخوشایندی ناراضی بودم. این تقریباً 40 انیمیشن خواهد بود :root اگر ادامه می دادم

پس رفتم بخوابم

وقتی از خواب بیدار شدم، چند لحظه همانجا دراز کشیدم و با آن احساس وزوز بیدار یا مدیتیشن لبخند به بیرون از پنجره نگاه کردم، سپس شلنگی از افکار به سرم هجوم آورد. غلت زدم، نوت بوک و نزدیکترین خودکارم را برداشتم، روی تخت نشستم و شروع به نوشتن الگوریتمی کردم تا فقط با ۶ انیمیشن CSS آن را استخراج کنم.

دستخط مرغ من روی یک تکه کاغذ دفترچه خط دار با فلش هایی که به چند جعبه تودرتو اشاره دارد و روش شرح داده شده در زیر را شرح می دهد.

به معنای واقعی کلمه روی کاغذ حل شده است. این است دقیقا چگونه اجرا می شود

بلند شدم، سوار کامپیوترم شدم، کارهای قبلی ام را نادیده گرفتم و یک CodePen جدید باز کردم.

من 4 عنصر html مشخص شده در میان خراش مرغ را در آنجا تنظیم کردم، سپس پانل CSS را با یادداشت هایی در اطراف 4 انتخابگر کلاس خالی مربوط به آنها پر کردم. روشن نخواهد شد :root در حال حاضر، اما ما می توانیم هر چیزی که به آن متکی است را در داخل قرار دهیم.

تا زمانی که یادداشت ها از روی کاغذ کپی شده و با جزئیات دقیق تری در CodePen نوشته شدند، حتی یک بخش از عملکرد اضافه نشد.

وقتی کارم تمام شد، فقط یادداشت ها را خواندم و شروع کردم به اجرای آنچه گفته بودند، تا نتیجه نهایی کار.

(به جای 35 نوشتم “20” چون قرار بود با 256 بیت تست کنم)

من به نحوه عملکرد آن می پردازم. به دلیل خط زمانی و محدوده زمانی، می‌توانید داده‌ها را طوری تنظیم کنید که به شکل بطری کلاین جریان پیدا کنند، اگر بتوانید سطح را متحرک و در حال مکیده شدن به درون «سوراخ» تصویر کنید، از بالای باریک به پایین برگردید. دوباره روی سطح، اندازه و پیچیدگی را از طریق لایه‌های dom به دست می‌آورد، و سپس از طریق سیاه‌چاله به سمت آگاهی بالاتر (:root) برمی‌گردید.

بیشتر به صورت چرخه ای عمودی است (به جای چرخه ای عمدتاً افقی یا چرخه ای ایستا)

استخراج 512 بیت با CSS

یادداشت هایی که ما کمی تغییر دادیم و واضح تر بیان کردیم:

تست 256 -> 512 نهایی

و من یک گره ارائه در داخل آن اضافه کردم که عالی است زیرا می توانم داخلی ها را نیز در حین اجرای الگوریتم نشان دهم.

اما در اینجا نکات پایانی بدون تمام نویز اجرا و ارائه است. این دقیقاً توضیح می دهد که چگونه همه کار می کند.

ممکن است برای یک مقاله به شکل خوبی نباشد که این تعداد جزئیات در خارج از آن تعبیه شده باشد، اما من هر بخش را برای نشان دادن آن تجزیه می کنم. چگونه اجرا شده است.

کنترل کننده اصلی

در بالای این ساختار 4 مقدار تایم لاین و انیمیشن های آنها قرار دارد. پس بیایید آن ها را وارد کنیم.

بخش کلیدی جریان داده ای که این امکان را فراهم می کند، این است که به ما این توانایی را می دهد که داده های تو در تو در اعماق DOM را به یک میزبان (محدوده تایم لاین) برگردانیم. کارآمد نیست، بنابراین می‌خواهیم تعداد دفعات انجام این کار را محدود کنیم. هر ویژگی ثبت شده و انیمیشن آن می تواند به صورت عمودی میزبان یک تکه داده باشد. مقدار داده ها توسط inline یا block view موقعیت یک عنصر در جایی در اعماق ساختار – بعداً به آن قسمت خواهیم رسید.

(برای تصویر واضح تر از جریان داده به مثال حلقه ای که قبلاً در بالا تعبیه شده است مراجعه کنید)

چهار قطعه داده ای که در اینجا بلند می کنیم عبارتند از:

--xfl-cpu-phase – این یک مقدار عددی 0 تا 4 است که نشان می دهد چه مرحله ای از هک CPU در حال حاضر در حال اجرا است. (یک «فریم» از هک CPU، 4 تا 5 فریم رندر CSS است، یک حلقه از مراحل هک CPU را «تیک» می کند) در ادامه این مقاله این را به طور خاص نشان خواهم داد.

--xfl-raw-data – این میزبان ارتفاع SVG در هر کجای SVG در چرخه انیمیشن خود است. داده های خام ما همانطور که قبلاً گفته شد، اگر این مقدار کمتر از 35 باشد، این مرحله مجزا از انیمیشن SVG یک مقدار نگهبان است. اگر بزرگتر از 34 باشد، این مرحله مجزا از انیمیشن SVG مقدار 16 بیتی ما است. + 35، که با آنچه نگهبان قبلی اشاره کرد مطابقت دارد.

--xfl-data-type – این آخرین مقدار نگهبان است. این مقدار تا زمانی که نگهبان بعدی مواجه نشود تغییر نمی کند. 1 فریم CSS تاخیر از تنظیم وجود دارد --xfl-raw-data برای تنظیم این مقدار

--xfl-data-value – این مقدار داده فعلی پس از آن است 35 از مقدار خام کم شد یا 0 اگر هنوز به این مرحله از سکانس نرسیده ایم. 1 فریم CSS تاخیر از تنظیم وجود دارد --xfl-data-type برای تنظیم این مقدار

من هم پیشگیرانه بسته بندی کردم svg-animation-current-state-reporter در شرایطی که فقط دارای عملکرد است و فقط SVG متحرک را در حالی که فرآیند ناقص است بارگیری می کند. (بنابراین تمام موارد داخلی از حافظه حذف می شود و svg متحرک سنگین پس از اتمام از رندر حذف می شود)

مقادیر فریم کلیدی از a است max مقدار آن قطعه داده به 0 می رسد. بعداً توضیح خواهم داد که چرا اینها عقب هستند – به دنبال تصویر کارت های Uno Reverse باشید.

CPU Exfiltrator

در مرحله بعد، دیگ بخار اولیه را برای هک CPU تنظیم می کنیم

دیگ بخار CPU Hack فقط از یک الگوی نام متغیر برای راه اندازی پیروی می کند capture و hoist انیمیشن ها

اگر 1 عدد صحیح داشته باشیم --xfl\\1 که می خواهیم به صورت افقی چرخش کنیم (در طول زمان)، آن را ثبت می کنیم و انیمیشن های ضبط و بالا بردن را مانند این تنظیم می کنیم:

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

@keyframes hoist {
  0%, 100% {
    --xfl\\1-hoist: var(--xfl\\1-captured, 0);
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

سپس تکلیف چرخه ای را بر روی آن کامل کنید .cpu-exfiltrator عنصری که در آن دو انیمیشن CPU میزبانی می شوند. فعلا فقط برای یکی از مقادیر این کار را انجام می دهم:

  --xfl\\1: calc(
    var(--xfl\\1-hoist, 0) + 1
  );
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در کروم، آنها به طور ایستا چرخه نخواهند کرد (تبدیل به initial ارزش) مگر اینکه هر دو انیمیشن باشند running در همان زمان این یک عارضه جانبی فوق العاده است که احتمالاً بهینه سازی انیمیشن های متوقف شده با تنظیم ویژگی های عددی است.

در نهایت، از آنجایی که ما از یک نسخه خودکار جدید از هک CPU استفاده می کنیم (برای چرخه فازها مانند هک اصلی نیازی به :مانوس ندارید)، سیم کشی را وارد می کنیم. --xfl-cpu-phase var از قبلی (در اینجا بر روی عنصر والد میزبانی می شود، بنابراین می توانیم از پرس و جوهای سبک برای پاسخ به آن استفاده کنیم) و وضعیت پخش انیمیشن های خود را کنترل کنیم.

خروجی هم داریم --cpu-next-phase که بعداً به بالا برمی‌گردد و مقدار بعدی را برای --xfl-cpu-phase با استفاده از موقعیت دید و محدوده زمانی آن.

من یک مرحله اضافی اضافه کرده ام تا هک CPU را متوقف کنم تا زمانی که اندازه گیری انیمیشن SVG در مرحله بعدی با موفقیت قفل شود. --xfl-data-type

  @container style(--xfl-cpu-phase: 4) {
    animation-play-state: paused, paused;
    --cpu-next-phase: calc(
      min(1, var(--xfl-data-type)) * 4
    );
  }
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

(همانطور که الان هست، نوع داده همیشه همیشه 0 است، بنابراین وقتی فاز بعدی سیم‌کشی شد، هک CPU از قبل حلقه می‌شود. وقتی یک نگهبان نوع داده داشته باشیم، تا زمانی که آن را عمداً پاک نکنیم، حلقه نمی‌شود. با 0 نگهبان)

بعداً، شرایط ذکر شده را نیز اضافه می‌کنیم تا از شروع فاز 1 CPU تا زمانی که همه داده‌ها در جای خود قرار نگیرند، جلوگیری می‌کنیم. این اطمینان حاصل می کند که بین نوع داده (sentinel) که قفل می شود و مقدار داده (خام – 35) قفل می شود، می خواهیم هک CPU را در مرحله ضبط آن رها کنیم. بنابراین همانطور که آبراهام هیکس ممکن است بگوید “آماده برای آماده شدن است”.

من تمام 32 مقدار را به اضافه جمع و طولی که انتظار داریم انیمیشن SVG گزارش کند، ثبت می کنم.

از زمان ثبت نام --xfl\\1 به --xfl\\32 یک بلوک بزرگ است و انیمیشن‌های CPU نیز فقط یک صفحه بخاری هستند، من همه آن‌ها را به پایین تنظیمات هک منتقل می‌کنم تا در حرکت به جلو نادیده گرفته شوند.

هک خودکار CPU

این سیم فاز بعدی cpu را به --xfl-cpu-phase ارزش

.cpu-phase-cycle-request0r {
  display: block;
  position: absolute;
  overflow: hidden;
  background: hotpink;
  width: 100px;
  height: 10px;
  bottom: 100vh;
  &::before {
    content: "";
    position: absolute;
    left: 0px;
    top: 0px;
    height: 100%;
    width: calc(25px * var(--cpu-next-phase));
    background: lime;
    view-timeline: --xfl-cpu-phase inline;
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا مقداری دیگ بخار CSS وجود دارد تا عنصر را به یک محفظه اسکرول تبدیل کند و آن را از صفحه خارج کند. بخش مهم این است:

view-timeline: --xfl-cpu-phase inline;

که می گوید لبه سمت راست این عنصر شبه در والد عرض 100 پیکسلی آن کجا قرار می گیرد، آن را به عنوان یک “پیشرفت” از سمت چپ به انیمیشن ما که از 0 به 4 حرکت می کند، سیم کشی کنید… بنابراین 25 پیکسل 25٪ کامل است، که نگاشت به 1 زمانی که 25% بین 0 و 4 باشد.

تصویر دو کارت تصویر از جستجوی گوگل منتهی به توییتر گرفته شده است

از نظر فنی انیمیشن 4 به 0 است و از نظر فنی از لبه سمت راست شبه اندازه گیری می شود تا پیشرفت به سمت راست را مشاهده کنید. بنابراین، شبه عریض 25 پیکسلی، 75 درصد از سمت راست والد اسکرول عریض 100 پیکسلی آن است و زمانی که 75 درصد بین 4 و 0 است، به مقدار 1 نشان داده می شود.

اگر ریاضی معکوس را به صورت شناختی پردازش نکنید و فقط بپذیرید که نتیجه نهایی یک پیشرفت ساده 0 تا 4 است، درک آن آسانتر است زیرا حداکثر مقدار در انیمیشن 4 است (دوباره نادیده گرفتن انیمیشن شروع می شود در 4).

بیایید حالت آماده را نیز بنویسیم که CPU را در فاز 0 نگه می دارد تا داده ها آماده شوند. یادداشت در خط 64 دموهای ما قرار دارد:

Data ready = data-type > 0 && raw-frame-data - 35 === data-value

  --xfl-data-is-ready: calc(
    min(1, var(--xfl-data-type, 0)) *
    (1 - min(1, max(
      (var(--xfl-raw-data, 0) - 35) - var(--xfl-data-value, 0),
      var(--xfl-data-value, 0) - (var(--xfl-raw-data, 0) - 35)
    )))
  );
  @container style(--xfl-cpu-phase: 0) {
    animation-play-state: running, paused;
    --cpu-next-phase: var(--xfl-data-is-ready);
  }
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

صبر کنید، === در CSS؟

اینها اکنون کاملاً منسوخ شده اند و من امروز آنها را متفاوت انجام می دهم، قبلاً نوشته شده است clamp() پایه بود، اما من همیشه این کدپست قدیمی را باز می‌کنم تا در مواقعی که به مقایسه‌کننده‌های عددی نیاز دارم، بی‌خیال آنها را کپی کنم. به روز رسانی و توضیح آنها مقاله خوبی خواهد بود، اما در این میان به اینجا بروید: https://codepen.io/propjockey/pen/YzZMNaz

خواندن انیمیشن SVG

این در ابتدا است خیلی شبیه به CPU Exfiltrator بخش چون همان تکنیک است، اندازه‌گیری و انتقال داده‌ها از اینجا به DOM به جایی که میزبان آن است (محدوده).

ما 3 مقدار آخر را برای عنصر پایه ای که در ابتدا تنظیم کردیم اندازه گیری و گزارش خواهیم کرد.

روشن ::before ما SVG را رندر می کنیم و تنظیم می کنیم --xfl-raw-data با استفاده از block موقعیت نمایش که اندازه گیری ارتفاع SVG متحرک است. (به یاد داشته باشید که عرض را به آن پین می کنیم 10px)

روشن ::after تنظیم می کنیم --xfl-data-type درون خطی (مقادیر نگهبان 0 تا 34) و --xfl-data-value بلوک (مقادیر 16 بیتی).

والد باید به اندازه کافی پهن باشد تا SVG را رندر کند (حداقل 10 پیکسل) و اندازه گیری های دقیقی را برای مقادیر نگهبان (0 تا 34) ارائه دهد.

والد همچنین باید به اندازه کافی بلند باشد تا مقادیر 16 بیتی (35+) را اندازه گیری کند. از آنجایی که ما یک مقدار حداکثر را در مرحله اول 100k تنظیم کردیم، فقط از آن استفاده خواهیم کرد، حتی اگر حدود 30٪ بزرگتر از نیاز ما باشد.

و آن را از صفحه به بالا و چپ ببرید تا باعث ایجاد نوارهای اسکرول نشود.

بنابراین،

.svg-animation-current-state-reporter

می شود

  position: absolute;
  background: rgba(255, 0, 0, 0.5);
  width: 34px;
  /* --xfl-data-type keyframes are 34 to 0 b/c max data-type = 34 */
  height: calc(var(--xfl-max) * 1px);
  bottom: calc(var(--xfl-max) * 1px + 100vh);
  left: calc(-100vw - 100px);
  overflow: hidden;
  font-size: 0px!important;
  line-height: 0px!important;
  margin: 0px;
  padding: 0px;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و قبل از تبدیل شدن

    &::before {
      content: url('http://css-api.propjockey.io/api.svg.php?');
      position: absolute;
      background: lime;
      left: 0px;
      top: 0px;
      width: 10px!important;
      --height: 2135px;
      font-size: 0px!important;
      line-height: 0px!important;
      view-timeline: --xfl-raw-data block;
    }
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و ::after می شود

  position: absolute;
  width: 1px;
  height: 1px;
  left: calc(
    var(--TODO_SENTINEL_VALUE, 0) * 1px - 1px
  );
  top: calc(
    var(--TODO_DATA_VALUE, 0) * 1px - 1px
  );
  background: black;
  view-timeline: --xfl-data-type inline, --xfl-data-value block;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اساساً رسانه ذخیره‌سازی در اینجا برای این مقادیر بعد، موقعیت نمای یک شبه مربع 1 پیکسلی در برابر محفظه اسکرول والد آن است. در محاسبه‌های سمت چپ و بالا 1px کم می‌کنیم زیرا خود شبه 1×1 است و می‌خواهیم زمانی که مقدار مربوطه 0 است، 0 گزارش شود.

این همه بسیار شبیه به آنچه قبلا انجام شده است.

پیچیدگی‌های متعددی برای محاسبه این مقادیر وجود دارد، همانطور که یادداشت نشان می‌دهد:

/* there's 4 stages here
// 1) cpu tells us to reset to 0s
// 2) cpu is in phase 0 (capture running) and stays until these stages finish
//   a. if svg animation frame (based on raw) is type, set type else use prev
//   3. if svg animation frame (based on raw) is data, set data else use prev
// 4) CPU is executing, our job is to hold prev values and ignore the SVG ani
*/
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نکته کلیدی برای درک چگونگی حل این است که هر مقدار مقایسه کننده بر روی 0 یا 1 تنظیم می شود. اگر درست باشد 1، اگر نادرست باشد 0. سپس آن را در مقداری ضرب کنید. اگر نادرست باشد، نتیجه 0 می ماند، در غیر این صورت هر مقداری که باشد می شود.

آنا تودور به عمق زیادی از نحوه عملکرد این ایده در اینجا می پردازد

سپس، اگر آن مقایسه را دو بار انجام دهیم، با یک مقایسه متفاوت یا مخالف برای مقدار دوم، و آنها را با هم جمع کنیم (با اطمینان از اینکه حداکثر یکی از مقایسه‌کننده‌ها 1 است)، جمع دو مورد از آنها فقط گفتن “دیگر اگر” است.

if not ready * use the old value + else
if is ready * use this new value

به این صورت است که در طول مدت مرحله گسسته انیمیشن SVG برای مقدار پس از اینکه نوع قبلاً گزارش شده است، مقدار نگهبان را حفظ می کنیم.

کد CSS که آن را پیاده سازی می کند در خط 191 در اینجا، درست بالای بلوک بزرگ شروع می شود --xfl\\... ثبت املاک ما به سمت پایین قرار داده است
@property --xfl\\1 { syntax: ""; initial-value: 0; inherits: true; }

و حاوی نکات اضافی است:

تنظیم مقادیر خاص CSS –var (تکالیف آدرس داده شده)

منطقی که ما به آن اشاره کردیم دقیقاً همان مفهومی است که برای همه آنها استفاده می کنیم --xfl\\12, 32 مقادیر.

  --xfl-set\\1: calc(
    (1 - min(1, max(
      1 - var(--xfl-data-type, 0),
      var(--xfl-data-type, 0) - 1
    ))) * var(--xfl-data-is-ready)
  );
  --xfl\\1: calc(
    var(--xfl-set\\1) * var(--xfl-data-value, 0) +
    (1 - var(--xfl-set\\1)) * var(--xfl\\1-hoist, 0)
  );
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

شما بخوانید --xfl-set\\1 به عنوان if --xfl-data-type equals 1 use --xfl-data-is-ready با یک ضمنی else 0

--xfl-data-is-ready قبلاً به‌عنوان پرچمی ایجاد شد که ما را در فاز 0 نگه می‌دارد تا زمانی که به فاز 1 برگردیم.

یعنی شرایط ما اینطور است && منطق هر دو پرچم برای عبور باید 1 باشند.

سپس به خواندن ادامه می دهید --xfl\\1 به عنوان if --xfl-set\\1 use --xfl-data-value (مقدار فعلی SVG Animation) دیگر if NOT --xfl-set\\1 use --xfl\\1-hoist (مقدار قبلی که هک CPU برای –xfl\1 نگه می داشت)

این بسیار تکراری است و تقریباً کل بقیه این اکسفیلتراسیون را توصیف می کند.

مراحل نهایی در حال اجرا هستند calc() و mod() ریاضی برای ساختن چک‌سوم همانطور که قبلا توضیح داده شد، سپس اگر چک‌جمع محاسبه‌شده === چک‌جمع تعبیه‌شده در انیمیشن SVG را به هک CPU اضافه کنید تا بدانیم چه زمانی کامل شده است. همه بیشتر یکسان.

پس الان وقتشه 🙂

ارائه: CSS Animated SVG Exfiltration Hack

از آنجایی که می‌خواستم به تک تک تکه‌های این هک یک مقدار به ازای هر عنصر نشان دهم، ارائه برای این به طرز ناخوشایندی سنگین است. بیش از 2000 خط HTML و بیش از 400 خط CSS. به علاوه من از css-bin-bits برای تبدیل هر ثبات به باینری و غیره استفاده می کنم.

(روی اجرای مجدد در سمت راست پایین قاب کدپن کلیک کنید تا آن را در زمان واقعی مشاهده کنید!)

بدون جاوا اسکریپت!


تماس 👽 را باز کنید

لطفاً اگر فکر می‌کنید این درست است و می‌خواهید بیشتر بیاموزید، تماس بگیرید! همیشه از پاسخگویی به سوالات خوشحالم.

🦋@JaneOri.PropJockey.io

𝕏@Jane0ri

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا