وقتی باگ انیمیشن اصلاً باگ زمانبندی نیست
خلاصهٔ کاملتر
تو این مقاله کارل کخ تعریف میکنه که داشته نوار ابزار شناور DuckDuckGo روی iOS رو صیقل میداده؛ یه کپسول شیشهای که مثل Safari موقع اسکرول جمع میشه. گذار بین تبسوییچر و صفحهٔ وب یه تصویر شبحمانند میساخت: دو نسخهٔ رویهمافتاده از دکمههای عقب و جلو، شمارندهٔ تب و دکمهٔ منو. سه دور تنظیم مدت و منحنی انیمیشن فقط شکل شبح رو عوض کرد و به گفتهٔ نویسنده همین خودش نشونهٔ اینه که داری پارامترهای مکانیزم اشتباه رو دستکاری میکنی.
راهحل از اندازهگیری اومد نه حدس. اون گذار رو با حالت انیمیشن آهستهٔ شبیهساز و کندی ۱۰ برابر روی ۶۰ فریم بر ثانیه ضبط کرد و با ffmpeg فریمبهفریم جلو رفت. اونجا معلوم شد شمارندهٔ تب روی نوار ابزار واقعی، ۲۴ فریم قبل از اینکه انیمیشن snapshot اصلاً شروع بشه کاملاً دیده میشده. مقصر یه completion handler ناهمگام بود که بعد از بستن تبسوییچر، شفافیت نوار ابزار رو بیخبر از گذارِ در جریان روی حالت کامل میذاشت.
چون سه مسیر کد دیگه هم میتونستن همین کارو بکنن، نویسنده یه فلگ مالکیت اضافه کرد که همهٔ مسیرهای نویسنده روی اون property بهش احترام بذارن و دقیقاً تا وقتی روشن بمونه که گذار مالک ویوئه:
var isTabSwitcherTransitionOwningToolbar = false
if !isTabSwitcherTransitionOwningToolbar {
viewCoordinator.toolbar.alpha = toolbarAlpha(for: percent)
}باگ دوم بعد از رفع شبح خودشو نشون داد. کپسول عمداً کمی بیرون از bounds خودش کشیده میشه تا کنار نوار خانه شناور بمونه، ولی snapshotView(afterScreenUpdates:) فقط محدودهٔ bounds رو میگیره؛ پس ته کپسول با گوشههای گرد و سایه از تصویر بریده میشد. باگ سوم هم موقع باز کردن تبسوییچر در نمای لیستی لوگوی Dax رو به بیضی پهن تبدیل میکرد، چون resizableSnapshotView بهجای مقیاسکردن، کشش غیریکنواخت میده و ردیف لیست تقریباً شش برابر ارتفاعش عرض داره.
جواب درست این بود که مقیاس روی کوچکترین نسبت بین عرض و ارتفاع حساب بشه تا تصویر واقعاً کوچیک بشه و برش نخوره:
let scale = min(
containerBounds.width / sourceSize.width,
containerBounds.height / sourceSize.height
)نویسنده توصیه میکنه هر گذاری که بهجای ویو زنده روی snapshot انیمیشن میده رو از دو زاویه چک کنین: گرفتن bounds بهجای محدودهٔ واقعیِ ترسیم، و resize کردن بهجای scale کردن. هر دو از کدریویو رد میشن، چون تو همون نسبت تصویری که تست کردی درست به نظر میرسن.
نکات کلیدی:
- تصویر شبحمانند از یه completion handler ناهمگام میاومد که ۲۴ فریم قبل از شروع انیمیشن snapshot، نوار ابزار رو کاملاً مات میکرد
- ضبط با کندی ۱۰ برابرِ شبیهساز و مرور فریمبهفریم با ffmpeg ابزار پیدا کردن ریشه بود
- snapshotView(afterScreenUpdates:) فقط bounds ویو رو میگیره، پس سایه و گوشههای بیرونزده بریده میشن
- resizableSnapshotView تصویر رو غیریکنواخت میکشه؛ مقیاس درست با min بین نسبت عرض و ارتفاع به دست میاد
- سه مسیر کد دیگه هم میتونستن شفافیت نوار ابزار رو بنویسن، برای همین یه فلگ مالکیت مشترک لازم شد




