احترام به طراحی عمدی با لوتی – مجله Smashing

هنگامی که توسعه دهندگان فرانت اند و مهندسان UX وظیفه دارند یک رابط وب ایجاد کنند که احساس لمس، جهش یا اختلال ایجاد کند، غریزه صنعت تقریباً همیشه یکسان است: دستیابی به یک موتور فیزیکی. چارچوبهایی مانند Matter.js، Cannon.js یا راهحلهای سفارشی WebGL به استاندارد طلایی برای ایجاد وبسایتهای جذاب و گیمیشده تبدیل شدهاند.
هنگامی که تیم ما در آژانس Isadora قصد ساخت Stress Release را آغاز کرد، یک اسباببازی دیجیتالی برای کاهش استرس که طراحی شده بود تا به خلاقان سوخته اجازه دهد شخصیتهای UI متحرک را بشکنند، کشش دهند و بچرخانند، ما در ابتدا این مسیر را بررسی کردیم. هدف این بود که یک تجربه بسیار لمسی که در آن هر کلیک یک پاسخ رضایت بخش و نرم را ایجاد می کند.
اما زمانی که نمونهسازی اولیه را شروع کردیم، متوجه یک چیز بسیار مهم شدیم: موتورهای فیزیک حرکت باورنکردنی تولید میکنند، اما در مورد ما، انیماتورها تولید میکنند. حرکت عمدی.
ما نیازی نداشتیم که شخصیتهایمان مانند توپهای لاستیکی واقعگرایانه عمل کنند که بهطور غیرقابل کنترلی دور یک بوم میپرند. ما به آنها نیاز داشتیم که به روش های بسیار خاص و به خوبی طراحی شده واکنش نشان دهند. بنابراین موتور فیزیک را به طور کامل حذف کردیم.
در این مقاله، نحوه ایجاد یک اسباببازی فشاری کاهش استرس را در زمان واقعی توضیح خواهیم داد بدون یک خط WebGL یا Matter.js، با تکیه کامل به کنترل های برنامه ای حالت Lottie، دستکاری DOM و ریاضیات مبتنی بر فاصله.
الزامات طراحی: حرکت عمدی
نیاز اساسی ما برای تسکین استرس بود کنترل قطعی مطلق. انیماتورهای ما به سفارش ساخته شده اند .json فایلهای Lottie که نیاز به سازگاری دقیق فریم به فریم دارند.
به عنوان مثال، پاسخ “مگا فشار” ما به ساخت دقیق 181 فریم و به دنبال آن یک توالی انتشار خاص نیاز دارد. برای احترام به این طراحی، به معماری نیاز داشتیم که فریمهای کلیدی ایجاد شده توسط انیماتورها را با تقریبهای الگوریتمی بازنویسی نکند.
هرچه زنجیره کلیک-بازخورد محکم تر باشد (کلیک کنید ← له کردن → نتیجه)، بیشتر به کنترل قاب قطعی نیاز دارید. با انتخاب کنترل حالت برنامهای با استفاده از API خود Lottie، اطمینان حاصل کردیم که لایه تعامل به عنوان یک ماشه بیعیب برای لایه انیمیشن عمل میکند.

ایجاد بازخورد لمسی: نگاشت عناصر DOM به ایالات Lottie
از آنجا که معماری ما به Lottie و DOM استاندارد متکی است، رندر مستقیماً توسط زمان اجرا Lottie انجام می شود که انیمیشن های برداری مبتنی بر JSON را به صورت SVG در داخل ارائه می کند. ما عناصر را مستقیماً بر اساس ID و کلاس CSS انتخاب کردیم و رفتار آنها را با استفاده از ترکیبی از بخشهای انیمیشن Lottie، تبدیلهای CSS و ریاضیات رویداد کلیک کنترل کردیم.
برای دستیابی به یک «احساس لمسی» عمیقاً رضایتبخش هنگام ضربه زدن به یک شخصیت، از آن استفاده کردیم نگاشت ورودی شعاعی. اولین مرحله تبدیل کلیک از مختصات صفحه به فضای مختصات محلی کاراکتر بود.
هر کلیک با نقطه مرکزی شخصیت اندازه گیری می شود، سپس به امتیاز، شدت بازخورد و محل انفجار ترجمه می شود:
// Character's center point in its own coordinate space
var x_center = parseFloat($("#playChar").width() / 2);
var y_center = parseFloat($("#playChar").height() / 2);
// Click position relative to the character's top-left corner
var offset = $("#playChar").offset(); // document-relative position
var X = parseFloat(e.pageX - offset.left);
var Y = parseFloat(e.pageY - offset.top);
// Vector from center to click point
var a = parseFloat(X - x_center);
var b = parseFloat(Y - y_center);
سپس فاصله خط مستقیم از مرکز کلیک را با استفاده از قضیه فیثاغورث محاسبه می کنیم:
var distance = Math.hypot(a, b);
این عدد واحد همه چیز را کنترل می کند: امتیاز، شدت بازخورد و جایی که انیمیشن انفجار ظاهر می شود:
// Distance zones map to point rewards
if (distance
نتیجه سیستمی از مناطق متحدالمرکز است – یک دایره کامل از حلقه های امتیازدهی در اطراف مرکز شخصیت، بسیار شبیه به دارت. پیچیدگی بصری Lottie SVG کاملاً بی ربط به تشخیص ضربه است. hitbox همیشه یک دایره تمیز است. به طور بحرانی، انیمیشن انفجار Lottie به (a, b) تغییر مکان می دهد – همان بردار مورد استفاده برای امتیاز دادن، بنابراین همیشه دقیقاً در جایی که بازیکن کلیک کرده است ظاهر می شود. این دقت فضایی لامسه را ایجاد می کند “من آن را زدم” کاملاً از طریق موقعیت یابی ریاضی و DOM احساس کنید.

مدیریت تعامل: کنترل روایت
از آنجایی که این تجربه از عناصر SVG مبتنی بر DOM استفاده میکند، کلیکهای دسکتاپ و لمسهای تلفن همراه را میتوان مستقیماً از طریق شنوندگان رویداد بومی مدیریت کرد. این کار از لایههای raycast اضافی یا هماهنگی مجدد جلوگیری میکند و در عین حال مدل تعامل را با نحوه رندر کردن انیمیشنها مطابقت میدهد.
از آنجایی که بازی در یک نقطه خاص نیاز به یک پاسخ بصری دارد، Lottie تمام احساسات له شدن و پرش را از طریق منحنی های انیمیشن خود کنترل می کند. هر شخصیت دارای مجموعه ای تعریف شده از بخش های انیمیشن (حلقه های بیکار، فریم های واکنش و حالت های پایانی) است که به عنوان محدوده فریم ذخیره می شوند. هنگامی که یک کلیک رخ می دهد، ما مستقیماً به بخش دقیقی می پریم که با وضعیت فعلی بازی مطابقت دارد:
// Animation sections defined as frame ranges per character
const play_segments = [{
charId: 0,
sections: {
idle: [0, 40], // looping idle state
squeeze1: [41, 80], // light reaction
squeeze2: [81, 120], // medium reaction
squeeze3: [121, 160], // heavy reaction
},
playOrder: ["squeeze1", "squeeze2", "squeeze3"],
endAnimation: [161, 200]
}];
با هر کلیک، در صف پخش پیش می رویم و بخش بعدی را فعال می کنیم:
function stepAnim() {
let p = play_segments[0];
let i = p["playOrder"][curr_order_play];
let playNow = p["sections"][i];
playChar.stop(); // halt current segment immediately
playChar.loop = false; // no looping - play once and stop
playChar.playSegments(playNow, true); // jump to exact frames, force immediately
curr_order_play++;
canPlayAnim = 0; // lock out further clicks mid-animation
if (curr_order_play > p["playOrder"].length - 1) {
curr_order_play = 0; // cycle back to start of sequence
}
}
وقتی بخش کامل شد، کنترل به حلقه بیکار باز می گردد:
playChar.onComplete = function() {
canPlayAnim = 1; // unlock clicks again
if (!playEnd) playIdleState();
};
function playIdleState() {
playChar.playSegments([0, 40], true); // return to idle loop
playChar.loop = true;
}

و برای ایجاد مگا فشار، نوار در محدوده خاصی از فریم ها می چرخد تا زمانی که فعال شود:
// Loop the "ready to release" frames until player activates
indikL.loop = true;
indikL.playSegments([181, 302], true);
// On activation - play the release sequence once
indikL.loop = false;
indikL.playSegments([96, 396], true);
indikL.goToAndStop(0, true); // hard reset after completion
مزیت پاسخگو عناصر DOM
یکی دیگر از عوامل مهم در تصمیم معماری ما بود رفتار پاسخگو. چون ما ساختیم تسکین استرس در DOM پیچیدگی مقیاس بندی جعبه های مرزی و بردارهای برخورد بین دستگاه های مختلف را دور زدیم.
ما به طور کامل تغییر اندازه تطبیقی را پوشش داده ایم متغیرهای CSS. با محاسبه مجدد ویژگیهای CSS سفارشی در هر تغییر اندازه، طرحبندی به سادگی به متغیرهای بهروز شده واکنش نشان میدهد و Lottie SVGها به طور طبیعی در کانتینرهای خود مقیاس میشوند بدون اینکه حالت خود را از دست بدهند:
const appHeight = () => {
const doc = document.documentElement;
doc.style.setProperty("--doc-height", `${window.innerHeight}px`);
doc.style.setProperty("--doc-width", `${doc.clientWidth}px`);
};
window.addEventListener("resize", appHeight);
appHeight(); // run immediately on init
بهینه سازی عملکرد موبایل: قیمت Lottie
در حالی که این معماری به ما کنترل کامل بر مسیر هنری می داد، چالش متفاوتی را معرفی کرد: اندازه فایل.
فایل های Lottie JSON می توانند سنگین باشند. ما 21 انیمیشن شخصیت های مختلف، به علاوه چندین نوع انفجار داشتیم که همه باید بارگذاری می شدند. برای اطمینان از روان ماندن تجربه – به ویژه در دستگاه های تلفن همراه – چندین استراتژی بهینه سازی تهاجمی را اجرا کرده ایم:
- نظارت بر اتصال
ما زمان بارگذاری اولیه دارایی را با استفاده ازperformance.now()برای شناسایی اتصالات آهسته و علامت گذاری زمانی که زمان بارگذاری بیش از 5 ثانیه است. - بارگیری متوالی دارایی ها
بهجای اینکه همه ۲۱ انیمیشن کاراکتر را بهطور همزمان مقداردهی کنیم، آنها را با استفاده از یک انتظار به صورت جفت بارگذاری میکنیم و تنها با تکمیل هر جفت پیشرفت میکنیم. این مانع از مسدود کردن یک سری درخواستهای شبکه و رندر همزمان مرورگر در دستگاههای ارزانقیمت میشود. - مدیریت حافظه تهاجمی
بهجای اینکه انیمیشنهای انفجاری سنگین خود را در حافظه نگه داریم، آنها را در حال نابودی و بازسازی میکنیم. این یک هزینه نمونه کوچک را با ردپای حافظه بیکار بسیار کمتر عوض می کند. - تنزل رتبه پویا
Downgrade یک فراخوان API واحد است که بلافاصله پس از بارگیری هر نماد در قفسه اعمال می شود. نکته کلیدی اعمال سطوح مختلف کیفیت بسته به نقش شخصیت در صحنه است:
// Shelf screen - 21 animations playing simultaneously
shelf = lottie.loadAnimation({
container: document.getElementById("charShelf" + i),
renderer: "svg",
loop: true,
autoplay: true,
path: "assets/shelf/" + shelfFolders[i] + "/" + shelfFolders[i] + ".json",
});
lottie.setQuality(0.5); // 50% quality - reduces interpolation calculations
shelf.setSpeed(0.6); // 60% speed - fewer frame calculations per second
// Play screen - single focused character
playChar = lottie.loadAnimation({
container: document.getElementById("playChar"),
renderer: "svg",
loop: true,
autoplay: true,
path: chosenChar.url,
});
lottie.setQuality(1); // full quality - only one animation at a time
نتیجه گیری: انتخاب تکنولوژی مناسب برای طراحی
هنگام تعریف پشته برای یک تجربه وب گیمیفی، بسیار مهم است که اجازه دهید الزامات طراحی، تکنولوژی را دیکته کنند.

از آنجایی که تعاملات ما به پاسخ های بصری فردی و بسیار کنترل شده نیاز داشت، ما انتخاب کردیم کنترل وضعیت برنامه بیش از یک شبیه سازی در حال ظهور این راه حل به انیماتورها اجازه داد تا احساس دقیق تجربه را دیکته کنند و کد را به بهترین نحو انجام دهند: گوش دادن، محاسبه و عمل کردن.
منابع اضافی
آیا میخواهید خودتان آن را پیادهسازی کنید یا ببینید دقیقاً چه حسی در مرورگر دارد؟ این منابع را بررسی کنید:
- با کد بازی کنید
ما یک نمونه آزمایشی ساده برای CodePen آماده کردهایم که یک کاراکتر پاسخگوی کلیک را با استفاده از نشان میدهدplaySegments(). - محصول نهایی را ببینید.
برای مشاهده تمامی 21 نشانه و استراتژی های بهینه سازی در عمل، سایت Stress Release Live را بررسی کنید. - اسناد را بخوانید.
برای کسب اطلاعات بیشتر در مورد کنترلهای پخشکننده که استفاده میکنیم، اسناد رسمی وب Lottie را بررسی کنید. به طور خاص، کاوش کنیدloadAnimation()،playSegments()،setSpeed()، وsetQuality()– چهار روشی که کل لایه تعامل را که در این مقاله توضیح داده شده است، نیرو می دهد.
(Yk)



