التفاصيل

كم مرة تحصل على 404 صفحة؟ عادة ، لا يتم تصميمها وتبقى مفترضة. لقد عثرت مؤخرًا على test.do.am أي شخصية تفاعلية تجذب الانتباه وتنشط صفحة الخطأ.

ربما ، كان هناك مجرد صورة قطة ، ثم فكروا في حركة العينين وقام المطور بتنفيذ الفكرة. صورة الآن يزور المستخدم الصفحة ويفحص التأثير. إنها ميزة صغيرة رائعة وممتعة ، حيث تكتشفها ، ثم يناقشها المستخدم مع الزملاء أو الأصدقاء ، وحتى يكررها. قد يكون هذا سهلاً ، إن لم يكن:

  1. لا يتم تجديد نقطة الوسط عندما يقوم المستخدم بتغيير حجم النافذة. افتح نافذة المتصفح ذات إطار عرض صغير الحجم وتغيير حجمها إلى وضع ملء الشاشة ، ولا يظهر القطة في المؤشر.
  2. توضع نقطة المنتصف على العين اليسرى ، وليس في مركز العين المجهر للدائرة.
  3. عندما يحوم المستخدم المؤشر بين العينين ، لا تتجمع تفاحات العيون ولا تركز. تتطلع العيون إلى ما لا نهاية ، ولهذا السبب لا تنظر القطة إلى المستخدم ، فهي تنظر إليه.
  4. حركات العيون فورية ، يجب أن تكون سلسة.
  5. تحدث حركات التفاح بسبب تغيير الهامش / يسار الهامش. هذا غير صحيح ، ابحث عن الشرح أدناه.
  6. عيون لا تتحرك إذا كان المؤشر تحت تذييل الصفحة.

ما أقترحه

لبداية ، دعونا ننفذ حركة عيون خالية من العيوب.

1. إعداد العلامات

<div class="cat"> <div class="cat__eye _left"></div> <div class="cat__eye _right"></div> </div> 

2. الحصول على روابط لعناصر العيون

 const cat = document.querySelector('.cat'); const eyes = cat.querySelectorAll('.cat__eye'); const eye_left = eyes[0]; const eye_right = eyes[1]; 

3. تسجيل مستمع الحدث mousemove والحصول على إحداثيات المؤشر:

 let mouseX; let mouseY; window.addEventListener('mousemove', e => { mouseX = e.clientX; mouseY = e.clientY; }) 

أقوم بإضافة مستمع mousemove على كائن إطار ، وليس نص المستند ، لأنني أحتاج إلى استخدام كل الشاشة للحصول على إحداثيات الماوس.

4. الحركة
بما أنني سأقوم بتنعيم الحركات ، فلا يمكنني إدارتها في معالج mousemove.

أضف طريقة تحديث سيتم جلبها بواسطة requestAnimationFrame والتي تتم مزامنتها مع تجديد المتصفح. تحدث التجديدات عادة 60 مرة في الثانية الواحدة ، لذلك نرى 60 صورة في الثانية كل 16.6 مللي ثانية.

إذا افترض المطور أن مستعرض المستخدم لا يمكنه دعم requestAnimationFrame ، فيمكن للمطور استخدام setTimeout backback أو polyfill الجاهزة

 window.requestAnimationFrame = (function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); }; })(); 

من أجل تجديد أو إحضار التحديث بشكل مستقر في الوقت المناسب ، قمت بالتسجيل بدأ متغير

 let started = false; let mouseX; let mouseY; window.addEventListener('mousemove', e => { mouseX = e.clientX; mouseY = e.clientY; if(!started){ started = true; update(); } }) function update(){ // Here comes eyes movement magic requestAnimationFrame(update); } 

وبهذه الطريقة أحضرت باستمرار طريقة التحديث وإحداثيات المؤشر. ثم أحتاج إلى الحصول على قيم لحركات التفاح داخل العينين.

أحاول تحريك كلتا العينين كعنصر واحد

 let dx = mouseX - eyesCenterX; let dy = mouseY - eyesCenterY; let angle = Math.atan2(dy, dx); let distance = Math.sqrt(dx * dx + dy * dy); distance = distance > EYES_RADIUS ? EYES_RADIUS : distance; let x = Math.cos(angle) * distance; let y = Math.sin(angle) * distance; eye_left.style.transform = 'translate(' + x + 'px,' + y + 'px)'; eye_right.style.transform = 'translate(' + x + 'px,' + y + 'px)'; 

بسيط جدًا: ابحث عن dx و dy ، وهما فرق الإحداثيات بين مركز العيون والماوس ، ابحث عن الزاوية من المركز إلى المؤشر ، باستخدام أساليب Math.cos و Math.sin ، احصل على قيمة حركة للأفقية والعمودية. استخدام المشغل الثلاثي والحد من منطقة حركة العين.


يتم إعطاء قيمة Y أولاً لطريقة Math.atan2 ، ثم قيمة x. نتيجة لذلك يلاحظ المستخدم عدم وجود حركات طبيعية للعينين ولا يوجد تركيز.

اجعل كل عيون تتحرك وتشاهد دون الرجوع إلى بعضها البعض.

 // left eye let left_dx = mouseX - eyesCenterX + 48; let left_dy = mouseY - eyesCenterY; let left_angle = Math.atan2(left_dy, left_dx); let left_distance = Math.sqrt(left_dx * left_dx + left_dy * left_dy); left_distance = left_distance > EYES_RADIUS ? EYES_RADIUS : left_distance; let left_x = Math.cos(left_angle) * left_distance; let left_y = Math.sin(left_angle) * left_distance; eye_left.style.transform = 'translate(' + left_x + 'px,' + left_y + 'px)'; // right eye let right_dx = mouseX - eyesCenterX - 48; let right_dy = mouseY - eyesCenterY; let right_angle = Math.atan2(right_dy, right_dx); let right_distance = Math.sqrt(right_dx * right_dx + right_dy * right_dy); right_distance = right_distance > EYES_RADIUS ? EYES_RADIUS : right_distance; let right_x = Math.cos(right_angle) * right_distance; let right_y = Math.sin(right_angle) * right_distance; eye_right.style.transform = 'translate(' + right_x + 'px,' + right_y + 'px)'; 


مثيرة للاهتمام ولكن أسوأ من النتيجة السابقة ، عيون تتحرك صعودا وهبوطا بشكل مستقل. لذا فقد استخدمت العرض التوضيحي الأول كميكانيكي حركة أساسي وجعل تفاح العينين يجتمعان عندما يكون المؤشر حول مركز الشخصية.

لن أصف الكود بالكامل ، يرجى العثور على نتيجة هنا:


بالتجربة والخطأ ، قمت بمطابقة المعلمات اللازمة لحركة العين والتركيز. حتى الآن أنا بحاجة إلى تجانس.

تجانس

ربط مكتبة TweenMax ورمز شيء من هذا القبيل؟

 TweenMax.to( eye, 0.15, {x: x, y: y}); 

ربط ليب بالكامل لمهمة بسيطة لا معنى له ، لذلك ، أنا جعل تجانس من نقطة الصفر.

ضع حالة وجود عنصر عين واحد فقط على الصفحة ومنطقة النزوح الخاصة به غير محدودة على الإطلاق. لتنعيم إحداثيات الماوس ، استخدم هذه الميكانيكا:

 const SMOOTHING = 10; x += (needX - x) / SMOOTHING; y += (needY - y) / SMOOTHING; eye.style.transform = 'translate3d(' + x + 'px,' + y + 'px,0)'; 

يمكنني استخدام translate3d لفصل العيون عن تيار عرض آخر وتسريعها.

الحيلة هي أن كل 16.6 مللي ثانية (60 صورة في الثانية) متغير x و y يميل إلى القيم المطلوبة. كل تجديد يغلق القيمة إلى ما هو مطلوب ل 1/10 من الفرق.

 let x = 0; let needX = 100; let SMOOTHING = 2; function update(){ x += (needX - x) / SMOOTHING; console.log(x); } 

ثم كل 16.6 مللي ثانية تجدد نحصل على تجانس بسيط وقيم س القادمة (تقريبا):

 50 75 87.5 93.75 96.875 98.4375 99.21875 99.609375 100 

بعض الحيل الغير واضحة:

- ابدأ هذا الفحص لتحسين عبء العمل

 if(x != needX || y != needY){ eye.style.transform = 'translate3d(' + x + 'px,' + y + 'px,0)'; } 

ولكن عليك أن تساوي x إلى needX عندما تقترب من أن مواقف العيون تكون متشابهة تقريبًا

 if(Math.abs(x - needX) < 0.25){ x = needX; } if(Math.abs(y - needY) < 0.25){ y = needY; } 

وإلا فإن قيم x و y سوف تصل إلى needX و needy لفترة طويلة ؛ لن تكون هناك اختلافات مرئية ، ولكن كل تغيير شاشة سيؤثر على أنماط العيون. راجع للشغل يمكنك التلاعب بها بنفسك.

 let x = 0; let needX = 100; let smoothing = 2; function update(){ x += (needX - x) / smoothing; if( Math.abs(x - needX) > 0.25 ){ // replace 0.25 with anything else and check number of x renewals. window.requestAnimationFrame(update); } else { x = needX; } console.log( x.toString(10) ); } update(); 

- إذا كانت الميكانيكا أعلاه واضحة ، يمكنك إنشاء تأثيرات أكثر تعقيدًا ، مثل الربيع. أبسط تجانس وللمؤشر تقريب يشبه هذا:

 x += (mouseX - x) / smoothing; y += (mouseY - y) / smoothing; 


أضف تجانسًا بين قيم الإحداثيات المطلوبة والقيم الحالية.


في بعض الأحيان يكون تقريب الحدود منطقيًا. يوجد مثال أعلاه حيث تتغير القيمة من 0 إلى 100 ، لذلك في قيمة التكرار الأولى تصل إلى "50" ، إنها رقم كبير جدًا لخطوة واحدة. هذه الميكانيكا كيندا تذكر مفارقة أخيل والسلحفاة


الغمز

إخفاء وإظهار تفاح العينين كل 2-3 ثوان. الطريقة الأكثر تافهة هي "العرض: لا شيء ؛" ، "التحويل: scaleY (N)" مع القيمة الديناميكية للمقياس y أكثر تعقيدًا قليلاً.

إنشاء 2 consts

const BLINK_COUNTER_LIMIT = 180 ؛ - عدد التجديدات قبل بدء الوميض ،
const BLINKED_COUNTER_LIMIT = 6 ؛ - عدد التجديدات خلال غمزة واحدة.

و 2 المتغيرات ، والتي القيم سوف تتغير كل التجديد.

 let blinkCounter = 0; let blinkedCounter = 0; 

مدونة الغمز

 let blinkTransform = ''; blinkCounter++; if(blinkCounter > BLINK_COUNTER_LIMIT){ blinkedCounter++ if(blinkedCounter > BLINKED_COUNTER_LIMIT){ blinkCounter = 0; } else { blinkTransform = ' scaleY(' + (blinkedCounter / BLINKED_COUNTER_LIMIT) + ')'; } } else { blinkedCounter = 0; } 

BlinkTransform هو متغير الحد الذي يحتوي على قيمة فارغة بين الغمز وتليها أثناء الغمز

 ' scaleY(0.17)' ' scaleY(0.33)' ' scaleY(0.50)' ' scaleY(0.67)' ' scaleY(0.83)' ' scaleY(1.00)' 

جميع العمليات الحسابية تعطي تحويلًا وميضًا متغيرًا ، يجب إضافة القيمة إلى تحويل cSS الخاص بالعيون. وبالتالي تتم إضافة السلسلة الفارغة في حالة تعطل 3s ولا تؤثر على مقياس العيون ، يتم إضافة قيمة css أثناء وميض.

 eye_left.style.transform = 'translate(' + xLeft + 'px,' + y + 'px)' + blinkTransform; eye_right.style.transform = 'translate(' + xRight + 'px,' + y + 'px)' + blinkTransform; 

درس القصة

كل يوم نلتقي بأشياء تبدو بسيطة وواضحة ولا نفهم أن هذه البساطة الخارجية تخفي عددًا هائلاً من الأسئلة والتحسينات. في رأيي الشيطان هو في التفاصيل التي تشكل النتيجة النهائية بأكملها. محمد علي ، أفضل ملاكم في القرن العشرين ، رفع كعب القدم الخلفية في لحظة مثقوبة. زادت هذه المناورة من مسافة الضربة الفعالة ومنحته المزيد من الفرص للفوز. عملت دائما.

ملاحظة: ليس لدي أي تأثير على الموقع وأتمنى ألا يسيء مالكوه إلى تعليقاتي. للراحة أنا اسمه أبل العين = العين في التعليمات البرمجية.

Source: https://habr.com/ru/post/ar443720/


All Articles