أيقونات التطبيقات القابلة للرمي في صفحتنا الرئيسية
في صفحتنا الرئيسية صندوق فيه أيقونات تطبيقاتنا. تسقط الأيقونات عند وصولكم إلى الصفحة، ويمكنكم التقاطها ورميها. وإذا نقرتم على أيقونة دون سحبها، تفتح صفحة ذلك التطبيق. استغرق الأمر عصر يوم واحد، وكانت بعض التفاصيل أكثر إثارة للاهتمام مما توقعنا.
لماذا صندوق؟
كانت الفكرة الأولى أن نترك الأيقونات تتطاير في أعلى الصفحة كلها. لكن العنوان الرئيسي والأزرار موجودان هناك، وأن تهبط الأيقونات فوق زر «Start a project» ثمن سيئ مقابل بعض المرح. لذلك جعلنا الصندوق بجانب المقدمة، مع تسمية على حافته، ليبقى اللعب في حدود معينة. وهو يملأ أيضًا فراغًا كان موجودًا أصلًا: المساحة الفارغة على يمين المقدمة والأزرار في الشاشات العريضة. أما على الهواتف فيظهر تحت الأزرار.
فيزياء حقيقية مع Matter.js
من السهل أن تكتبوا بأنفسكم كودًا لدوائر تصطدم ببعضها. لكن أيقونات التطبيقات مربعات بزوايا مستديرة، والمربع الذي يتدحرج كالعملة المعدنية يبدو خاطئًا من النظرة الأولى. والتقلب والتراكم بشكل سليم يحتاجان إلى محرك فيزياء حقيقي، فاستخدمنا Matter.js. كل أيقونة عبارة عن مستطيل بزوايا مستديرة (chamfer) تطابق نصف قطر زاوية الأيقونة البالغ 22%، داخل أربعة جدران ثابتة.
حجم المحرك 83KB، لذلك لا يُحمَّل إلا في الصفحة الرئيسية، وبعد أن تكتمل الصفحة، وفقط إذا لم يطلب الزائر تقليل الحركة.
عناصر DOM وليس canvas
يستطيع Matter.js الرسم على canvas، لكننا نستخدمه للحسابات فقط. أما الأيقونات فهي روابط عادية فيها صور، ويُحدَّد موضعها في كل إطار باستخدام CSS transform:
st.setProperty("--x", (b.position.x - size / 2) + "px");
st.setProperty("--y", (b.position.y - size / 2) + "px");
st.setProperty("--a", b.angle + "rad");
وبذلك يكون النقر رابطًا حقيقيًا، وتظهر الصور واضحة عند أي مستوى تكبير، وتحتفظ الأيقونات بالإطار والنمط نفسيهما المستخدمين في بقية الموقع.
الظل الذي يبقى في مكانه
يعتمد أسلوبنا على ظل حاد يمتد إلى الأسفل وإلى اليمين من كل عنصر. وعندما تضعونه على عنصر يدور، يدور الظل معه، فيتأرجح ظل الأيقونة الدوارة مثل عقرب الساعة. والحل هو تدوير إزاحة الظل في الاتجاه المعاكس في كل إطار:
// keep the shadow at (3px, 3px) in screen space while the icon turns by a
st.setProperty("--shadow-x", 3 * (Math.cos(a) + Math.sin(a)) + "px");
st.setProperty("--shadow-y", 3 * (Math.cos(a) - Math.sin(a)) + "px");
الإمساك والرمي
عند الضغط بالمؤشر نربط نابضًا (قيدًا في Matter.js) بين المؤشر والنقطة الدقيقة التي أمسكتم بها على الأيقونة، وليس مركزها، فتتأرجح بشكل طبيعي إذا أمسكتم بها من إحدى زواياها. وعند الإفلات تحتفظ بسرعتها، مع حد أقصى لها حتى لا تخترق الجدار إذا نفضتموها بقوة. وإذا تحرك المؤشر أقل من ست بكسلات، يُعدّ ذلك نقرة ويُفتح الرابط.
يبقى أعلى الصندوق مفتوحًا بينما تسقط الأيقونات من الأعلى، ثم يُغلق عندما تصبح كلها في الداخل، فلا تضيع أيقونة من الأعلى عند الرمي.
تفاصيل صغيرة
- الهبوط القوي يرسل موجة تموّج عبر الخلفية المنقطة للصفحة.
- تتوقف المحاكاة عندما يسكن كل شيء، وتتوقف مؤقتًا عندما يكون الصندوق خارج الشاشة، فلا تستهلك شيئًا أثناء القراءة.
- لا تسقط الأيقونات إلا عندما يظهر الصندوق على الشاشة. وعلى الهاتف يحدث ذلك عند التمرير إليه.
- بدون JavaScript، أو مع تفعيل تقليل الحركة، تبقى الأيقونات ساكنة في كومة مرتبة، وتبقى روابط أيضًا.
إنها فكرة صغيرة، لكنها تقول عن التطبيقات التي نصنعها أكثر مما تقوله جملة. وإذا أردتم شيئًا مثلها لموقعكم، راسلونا.
تابعوا القراءة: ما الذي تطلبه جعل مواقعنا جاهزة للوكلاء، أو WordPress 7.2 يصدر في 8 ديسمبر: ما الذي نختبره في إضافاتنا.