اللمس والماوس

معًا مرة أخرى لأول مرة

مقدمة

لما يقرب من ثلاثين عامًا، تمحورت تجارب حوسبة سطح المكتب حول لوحة المفاتيح والماوس أو لوحة اللمس كأجهزة إدخال رئيسية للمستخدمين. على الرغم من ذلك على مدى العقد الماضي، نقلت الهواتف الذكية والأجهزة اللوحية نموذج تفاعل جديدًا: اللمس. مع طرح أجهزة Windows 8 التي تعمل باللمس، والآن مع إطلاق جهاز Chromebook Pixel الرائع الذي تعمل باللمس، باتت اللمسات الآن جزءًا من تجربة الاستخدام المتوقعة على الكمبيوتر المكتبي. يتمثل أحد أكبر التحديات في بناء تجارب لا تعمل فقط على الأجهزة التي تعمل باللمس وأجهزة الماوس، ولكن أيضًا على هذه الأجهزة التي سيستخدم فيها المستخدم كلتا طريقتي الإدخال - وأحيانًا في وقت واحد!

ستساعدك هذه المقالة في فهم كيفية تضمين إمكانات اللمس في المتصفح، وكيفية دمج آلية الواجهة الجديدة هذه في تطبيقاتك الحالية، وكيفية عمل اللمس بشكل جيد باستخدام الإدخال بالماوس.

حالة اللمس في النظام الأساسي للويب

كان جهاز iPhone هو أول نظام أساسي شائع يحتوي على واجهات برمجة تطبيقات مخصّصة تعمل باللمس ومضمّنة في متصفّح الويب. أنشأ العديد من مورّدي المتصفِّح الآخرين واجهات برمجة تطبيقات مشابهة تم تصميمها لتكون متوافقة مع عملية تنفيذ نظام التشغيل iOS، والتي أصبحت موضّحة الآن في مواصفات"الإصدار 1 من أحداث اللمس". تتوفّر أحداث اللمس على كلّ من Chrome وFirefox على أجهزة الكمبيوتر المكتبي وSafari على iOS وChrome ومتصفّح Android على Android، بالإضافة إلى متصفّحات الأجهزة الجوّالة الأخرى مثل متصفِّح Blackberry.

كتب زميلي "بوريس سموس" برنامجًا تعليميًا رائعًا حول HTML5Rocks حول أحداث اللمس، ولا يزال هذا الدليل طريقة جيدة للبدء إذا لم يسبق لك الاطّلاع على أحداث اللمس. في الواقع، إذا لم يسبق لك التعامل مع أحداث اللمس، يُرجى قراءة هذه المقالة الآن قبل المتابعة. هيا، سأنتظر.

هل اكتملت العملية؟ والآن بعد أن أصبح لديك أساس أساسي في أحداث اللمس، يكمن التحدي في كتابة التفاعلات التي تعمل باللمس في أن تفاعلات اللمس يمكن أن تكون مختلفة قليلاً عن أحداث الماوس (ولوحة اللمس التي تحاكي الماوس وكرة التتبع) - وعلى الرغم من أن الواجهات التي تعمل باللمس تحاول عادةً محاكاة أجهزة الماوس، إلا أن هذه المحاكاة ليست مثالية أو كاملة؛ حيث تحتاج حقًا إلى العمل من خلال كلا نمطي التفاعل، وقد تحتاج إلى دعم كل واجهة على حدة.

الأهم من ذلك: قد يتمكن المستخدم من اللمس والفأرة

أنشأ العديد من المطوّرين مواقع إلكترونية ترصد بشكل ثابت ما إذا كانت البيئة المحيطة تتوافق مع أحداث اللمس، ثم تفترض أنّهم بحاجة إلى دعم أحداث اللمس (وليس الماوس). وأصبح ذلك الآن افتراضًا خاطئًا، لأنّ مجرد وجود أحداث اللمس لا يعني أنّ المستخدم يستخدم بشكل أساسي جهاز الإدخال باللمس. تتوافق حاليًا أجهزة مثل Chromebook Pixel وبعض أجهزة الكمبيوتر المحمولة التي تعمل بنظام التشغيل Windows 8 مع استخدام طريقتَي الإدخال "الماوس" و"اللمس"، وسيتم إجراء المزيد من هذه الأجهزة في المستقبل القريب. على هذه الأجهزة، من الطبيعي جدًا أن يستخدم المستخدمون كلاً من الماوس والشاشة التي تعمل باللمس للتفاعل مع التطبيقات، لذلك فإن "إتاحة اللمس" ليست هي نفسها "لا تحتاج إلى دعم الماوس". لا يمكنك التفكير في المشكلة على أنها "لا بد لي من كتابة نمطين مختلفين للتفاعل والتبديل بينهما"، فأنت بحاجة إلى التفكير في كيفية عمل كلا التفاعلين معًا وكذلك بشكل مستقل. أستخدم لوحة اللمس بشكل متكرر على جهاز Chromebook Pixel، لكنني أضغط على الشاشة وألمسها، فأنا أفعل ما أجده مناسبًا في التطبيق نفسه أو على الصفحة نفسها. ومن ناحية أخرى، نادرًا ما يستخدم بعض مستخدمي الكمبيوتر المحمول الذين لديهم شاشة تعمل باللمس الشاشة التي تعمل باللمس على الإطلاق، لذلك يجب ألا يؤدي استخدام الإدخال باللمس إلى إيقاف عنصر التحكّم في الماوس أو عرقلته.

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

إتاحة استخدام الماوس واللمس معًا

1- النقر والنقر - ترتيب الأشياء "الطبيعي"

تكمن المشكلة الأولى في أنّ الواجهات التي تعمل باللمس تحاول عادةً محاكاة نقرات الماوس - ومن الواضح أنّ واجهات اللمس تحتاج إلى العمل على التطبيقات التي تفاعلت فقط مع أحداث الماوس من قبل! ويمكنك استخدام هذا كاختصار - لأن أحداث "النقر" ستستمر تنشيطها، سواء نقر المستخدم بالماوس أو نقر بإصبعه على الشاشة. ومع ذلك، هناك مشكلتان في هذا الاختصار.

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

  1. بداية اللمس
  2. حركة اللمس
  3. اللمس
  4. تمرير الماوس
  5. mousemove
  6. تمرير الماوس
  7. تمرير الماوس
  8. نقرة

وهذا يعني بالطبع أنّك إذا كنت تعالج أحداث اللمس مثل البداية باللمس، عليك التأكّد من عدم معالجة حدث النقر و/أو الماوس المقابل. إذا تمكّنت من إلغاء أحداث اللمس (يمكنك استدعاء preventDefault() داخل معالج الأحداث)، لن يتم إنشاء أي أحداث للماوس عند اللمس. من أهم قواعد معالِجات اللمس:

مع ذلك، يمنع هذا أيضًا السلوكيات التلقائية الأخرى للمتصفّح (مثل التمرير) - على الرغم من أنّك عادةً ما تتعامل مع حدث اللمس بالكامل في المعالج، عليك إيقاف الإجراءات التلقائية. وبوجه عام، سيكون عليك إمّا التعامل مع جميع أحداث اللمس وإلغاؤها، أو تجنُّب استخدام معالج لهذا الحدث.

ثانيًا، عندما ينقر المستخدِم على عنصر في صفحة ويب على جهاز جوّال، يحدث تأخير لا يقل عن 300 ملّي ثانية على الأقل بين الصفحات غير المصمّمة للتفاعل على الأجهزة الجوّالة بين حدث البداية باللمس ومعالجة أحداث الماوس (الماوس). ويمكن إجراء ذلك باستخدام Chrome، ويمكنك تفعيل "محاكاة أحداث اللمس" في "أدوات مطوّري برامج Chrome" لمساعدتك في اختبار واجهات اللمس على نظام لا يعمل باللمس.

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

Chrome لنظام Android متصفح Android Opera Mobile لنظام التشغيل Android) Firefox لنظام Android متصفح Safari لنظام التشغيل iOS
إطار عرض غير قابل للتطوير بلا تأخير 300 ملي ثانية 300 ملي ثانية بلا تأخير 300 ملي ثانية
بلا إطار عرض 300 ملي ثانية 300 ملي ثانية 300 ملي ثانية 300 ملي ثانية 300 ملي ثانية

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

<meta name="viewport" content="width=device-width,user-scalable=no">

وبالطبع، قد لا يكون ذلك مناسبًا في بعض الأحيان، لأنّ ذلك يؤدي إلى إيقاف ميزة التكبير أو التصغير بإصبعين، والتي قد تكون مطلوبة لأسباب تتعلّق بتسهيل الاستخدام، لذا ننصحك باستخدامها باعتدال في حال إيقاف الميزة (في حال إيقاف ميزة "تحجيم مقياس المستخدمين"، قد تحتاج إلى توفير طريقة أخرى لزيادة سهولة قراءة النص في تطبيقك). لا ينطبق هذا التأخير أيضًا على متصفّح Chrome على أجهزة الكمبيوتر المكتبي التي تتيح اللمس، والمتصفحات الأخرى على الأنظمة الأساسية للأجهزة الجوّالة عندما تحتوي الصفحة على إطارات عرض غير قابلة للتطوير.

رقم 2: أحداث Mousemove لا يتم تنشيطها باللمس

وتجدر الإشارة إلى أنّ محاكاة أحداث الماوس في واجهة اللمس لا تمتد عادةً إلى محاكاة أحداث تحريك الماوس، لذا إذا أنشأتَ عناصر تحكُّم جميلة تعتمد على الماوس وتستخدِم أحداث تحريك الماوس، فلن تعمل على الأرجح مع جهاز يعمل باللمس ما لم تضِف أيضًا معالِجات تحريك الماوس تحديدًا.

عادةً ما تنفّذ المتصفّحات تلقائيًا التفاعل المناسب لتفاعلات اللمس على عناصر تحكّم HTML، لذا مثلاً، ستعمل عناصر التحكم في نطاق HTML5 فقط عند استخدام التفاعلات باللمس. ومع ذلك، إذا استخدمت عناصر التحكّم الخاصة بك، لن تعمل على الأرجح مع تفاعلات نوع النقر والسحب. وفي الواقع، بعض المكتبات الشائعة الاستخدام (مثل jQueryUI) لا تتيح بشكل أساسي التفاعلات باللمس بهذه الطريقة (على الرغم من أنّه بالنسبة إلى jQueryUI، هناك العديد من إصلاحات الرموز البرمجية لهذه المشكلة). كانت هذه إحدى المشكلات الأولى التي واجهتها عند ترقية تطبيق Web Audio Playground للعمل باللمس - كانت أشرطة التمرير مستندة إلى jQueryUI، لذا لم تعمل مع تفاعلات النقر والسحب. ثم قمتُ بالتغيير إلى عناصر التحكم في نطاق HTML5، وقد نجحت في ذلك. بدلاً من ذلك، بالطبع، كان بإمكاني ببساطة إضافة معالِجات Touchmove لتعديل أشرطة التمرير، لكن هناك مشكلة واحدة في ذلك...

رقم 3: Touchmove وMouseMove ليسا نفس الشيء

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

الطريقة الأكثر شيوعًا التي قد يؤدي بها هذا إلى إزعاجك هي إذا أزلت (أو غيرت) العنصر الذي بدأ المستخدم لمسه. على سبيل المثال، تخيل لوحة عرض دوّارة للصور مع معالج لمس على لوحة العرض الدوّارة بالكامل لإتاحة سلوك التمرير المخصّص. وعند تغيير الصور المتاحة، تتم إزالة بعض عناصر <img> وإضافة عناصر أخرى. إذا بدأ المستخدم بلمس إحدى تلك الصور ثم أزلتها، سيتوقف المعالج (الذي ينتمي إلى عنصر أصل عنصر الصورة) عن تلقّي أحداث اللمس (لأنه يتم إرسالها إلى هدف لم يعد متاحًا في الشجرة)، وسيبدو أنّ المستخدم يمسك إصبعه في مكان واحد على الرغم من أنه ربما انتقل وأزاله في النهاية.

يمكنك بالطبع تجنُّب هذه المشكلة عن طريق تجنب إزالة العناصر التي تحتوي (أو لديها أسلاف لديها) معالِجات لمس عندما تكون اللمسة نشطة. بدلاً من ذلك، أفضل إرشادات هي بدلاً من تسجيل معالِجات اللمس الثابتة/Touchmove، والانتظار إلى أن تحصل على حدث touchstart، ثم إضافة معالِجات touchmove/Touchend/touchcancel إلى target لحدث touchstart (وإزالتها عند الإنهاء/الإلغاء). وبهذه الطريقة ستستمر في تلقّي أحداث اللمس حتى إذا تم نقل/إزالة العنصر الهدف. يمكنك اللعب بها هنا قليلاً - المس المربع الأحمر واضغط مع الاستمرار على مفتاح Escape لإزالتها من نموذج العناصر في المستند (DOM).

رقم 4: اللمس و :التمرير

فصلت استعارة مؤشر الماوس موضع المؤشر عن التحديد النشط، وأتاح هذا للمطورين استخدام حالات التمرير لإخفاء وعرض المعلومات التي قد تكون ذات صلة بالمستخدمين. على الرغم من ذلك، فإنّ معظم الواجهات التي تعمل باللمس لا ترصد في الوقت الحالي وجود إصبع "مرور" فوق هدف، لذا فإنّ تقديم معلومات مهمة دلاليًا (مثل عرض النافذة المنبثقة "ما هو عنصر التحكّم هذا؟") استنادًا إلى التمرير هو أمر مانع، ما لم توفّر أيضًا طريقة سهلة الوصول إلى هذه المعلومات للوصول إلى هذه المعلومات. يجب توخي الحذر بشأن كيفية استخدام التمرير لنقل المعلومات إلى المستخدمين.

مع ذلك، من المثير للاهتمام، رغم ذلك، تشغيل CSS :hover pseudoclass CAN عن طريق واجهات تعمل باللمس في بعض الحالات، حيث يؤدي النقر على أحد العناصر إلى جعله نشطًا عندما يكون الإصبع أسفل الإصبع، كما يحصل أيضًا على حالة التمرير: (في متصفح Internet Explorer، لا يسري تحريك مؤشر الماوس إلا عندما يكون إصبع المستخدم منخفضًا، في حين تحافظ المتصفحات الأخرى على تأثير التمرير: حتى يتم النقر على الماوس أو النقر التالي عليهما.) هذه طريقة جيدة لجعل القوائم المنبثقة تعمل على واجهات اللمس - من الآثار الجانبية لتنشيط العنصر هو تطبيق حالة التمرير أيضًا. مثال:

<style>
img ~ .content {
  display:none;
}

img:hover ~ .content {
  display:block;
}
</style>

<img src="/awesome.png">
<div class="content">This is an awesome picture of me</div>

فبعد النقر على عنصر آخر، لا يعود العنصر نشطًا، وتختفي حالة التمرير، تمامًا كما لو كان المستخدم يستخدم مؤشر الماوس وتحريكه خارج العنصر. ننصحك بالتفاف المحتوى في عنصر <a> ليصبح علامة جدولة أيضًا، وبهذه الطريقة يمكن للمستخدم تبديل المعلومات الإضافية عن طريق التمرير بالماوس أو النقر أو اللمس أو الضغط على المفاتيح، بدون الحاجة إلى JavaScript. لقد تفاجأت عندما بدأت في العمل على تصميم Web Audio Playground (مساحة المرح لصوت الويب) بحيث يعمل بشكل جيد مع الواجهات التي تعمل باللمس حيث تعمل قوائمي المنبثقة بشكل جيد بالفعل، وذلك لأنني استخدمت هذا النوع من البنية.

تعمل الطريقة أعلاه بشكل جيد مع الواجهات التي تعتمد على مؤشر الماوس، وكذلك مع الواجهات التي تعمل باللمس. يختلف ذلك عن استخدام سمات "title" (العنوان) عند التمرير، والتي لن تظهر عند تفعيل العنصر:

<img src="/awesome.png" title="this doesn't show up in touch">

الطريقة رقم 5: اللمس مقابل دقة الماوس

رغم انعدام مفهوم الفئران عن الواقع، اتّضح أنّ هذه الأنظمة دقيقة للغاية، إذ إنّ نظام التشغيل الأساسي يتتبع دقة البكسل الدقيقة للمؤشر بشكل عام. ومن ناحية أخرى، تعلّم مطوِّرو الأجهزة الجوّالة أنّ اللمسات بالأصابع على شاشة اللمس ليست دقيقة، ويرجع ذلك في الغالب إلى حجم مساحة سطح الإصبع عند ملامسة الشاشة (وجزئيًا لأنّ أصابعك تحجب الشاشة).

وقد أجرى العديد من الأفراد والشركات أبحاثًا مكثفة في مجال المستخدمين حول كيفية تصميم التطبيقات والمواقع التي تستوعب التفاعل بالأصابع، وقد تمت كتابة العديد من الكتب حول هذا الموضوع. النصيحة الأساسية هي زيادة حجم مساحات اللمس من خلال زيادة المساحة المتروكة، وتقليل احتمال حدوث نقرات غير صحيحة، من خلال زيادة الهامش بين العناصر. (لا يتم تضمين الهوامش في معالجة رصد النتائج لأحداث اللمس والنقر، في حين يتم تضمين المساحة المتروكة). وكان من بين الإصلاحات الأساسية التي اضطررت إلى إجرائها على Web Audio Playground هو زيادة أحجام نقاط الاتصال بحيث يمكن لمسها بدقة أكبر.

لقد قدم العديد من موردي المتصفح الذين يتعاملون مع الواجهات التي تعمل باللمس ميزة منطقية في المتصفح للمساعدة في استهداف العنصر الصحيح عندما يلمس المستخدم الشاشة وتقليل احتمال حدوث نقرات غير صحيحة - على الرغم من أن هذا يؤدي في العادة إلى تصحيح أحداث النقر فقط، إلا أنه لا يتحرك (على الرغم من أن Internet Explorer يبدو أنه يعدّل أحداث الماوس لأسفل/ماوس/ماوس / الماوس أيضًا).

رقم 6: الحفاظ على معالِجات اللمس المتوفرة، أو التخلص من التمريرة

من المهم أيضًا إبقاء معالِجات اللمس تقتصر على العناصر التي تحتاج إليها فقط، حيث يمكن أن تكون عناصر اللمس ذات نطاق ترددي عالي جدًا، لذلك من المهم تجنُّب معالِجات اللمس ضمن عناصر التمرير (لأنّ المعالجة قد تتداخل مع تحسينات المتصفّح للتنقُّل السريع باللمس - تحاول المتصفِّحات الحديثة التمرير في سلسلة وحدة معالجة الرسومات، ولكن يكون ذلك مستحيلاً إذا كان عليهم التحقّق باستخدام JavaScript أولاً لمعرفة ما إذا كان يجب معالجة كل حدث لمس من خلال كل حدث لمس). يمكنك الاطّلاع على مثال على هذا السلوك.

ننصحك باتّباع الإرشادات التالية لتجنُّب هذه المشكلة: التأكّد من تثبيت معالِجات اللمس في جزء صغير من واجهة المستخدم فقط (وليس على <body> من الصفحة مثلاً)، وباختصار، عليك الحدّ من نطاق معالِجات اللمس قدر الإمكان.

7- اللمس المتعدد

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

إذا كنت تقوم بإنشاء تطبيقات تعمل بشكل أساسي بالماوس، فأنت بذلك معتاد على الإنشاء باستخدام نقطة مؤشر واحدة على الأكثر - لا تدعم الأنظمة عادةً مؤشرات الماوس المتعددة. بالنسبة إلى العديد من التطبيقات، سيكون عليك تعيين أحداث اللمس على واجهة مؤشر واحد، إلا أنّ معظم الأجهزة التي لاحظناها للإدخال باللمس على سطح المكتب يمكنها معالجة إدخالَين متزامنَين على الأقل، ويبدو أنّ معظم الأجهزة الجديدة تتيح 5 إدخالات متزامنة على الأقل. ولتطوير لوحة مفاتيح بيانو على الشاشة، قد تحتاج بالطبع إلى أن تتمكن من دعم عدة إدخالات متزامنة باللمس.

لا تحتوي واجهات برمجة التطبيقات W3C Touch API المنفذة حاليًا على واجهة برمجة تطبيقات لتحديد عدد نقاط الاتصال المتوافقة مع الأجهزة، لذا سيكون عليك استخدام أفضل تقدير لتحديد عدد نقاط الاتصال التي يريدها المستخدمون، أو بالطبع، انتبه إلى عدد نقاط الاتصال التي تراها عمليًا وتكييفها. على سبيل المثال، في تطبيق البيانو، إذا كنت لا ترى أبدًا أكثر من نقطتَي اتصال، فقد تحتاج إلى إضافة بعض واجهة مستخدم "الأوتار". تحتوي واجهة برمجة التطبيقات Pointerevents API على واجهة برمجة تطبيقات لتحديد إمكانات الجهاز.

اللمسات الأخيرة

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

إنّ اتّباع هذه الإرشادات ليس ممكنًا وحسب، بل هو سهل نسبيًا عند إنشاء تجارب تفاعلية جاذبة تعمل بشكل جيد من خلال الإدخال باللمس والإدخال بالماوس وحتى كلا أسلوبَي التفاعل في الوقت نفسه.