ডিফল্টরূপে দ্রুত স্পর্শ স্ক্রোলিং করা

ডেভ তাপুস্কা
Dave Tapuska

আমরা জানি যে মোবাইলে একটি ওয়েবসাইটের সাথে ব্যবহারকারীর ব্যস্ততার জন্য স্ক্রলিং প্রতিক্রিয়াশীলতা গুরুত্বপূর্ণ, তবুও স্পর্শ ইভেন্ট শ্রোতারা প্রায়শই গুরুতর স্ক্রলিং কার্যকারিতা সমস্যা সৃষ্টি করে। ক্রোম টাচ ইভেন্ট শ্রোতাদের প্যাসিভ হওয়ার অনুমতি দিয়ে ( {passive: true} addEventListener() ) বিকল্পটি পাস করে এবং পয়েন্টার ইভেন্ট এপিআই পাঠানোর মাধ্যমে এটির সমাধান করছে। নতুন বিষয়বস্তুকে মডেলে চালিত করার জন্য এগুলি দুর্দান্ত বৈশিষ্ট্য যা স্ক্রোলিংকে অবরুদ্ধ করে না, তবে বিকাশকারীরা কখনও কখনও সেগুলি বোঝা এবং গ্রহণ করা কঠিন বলে মনে করেন।

আমরা বিশ্বাস করি যে ডেভেলপারদের ব্রাউজারের আচরণের অত্যাশ্চর্য বিশদ বোঝার প্রয়োজন ছাড়াই ওয়েব ডিফল্টভাবে দ্রুত হওয়া উচিত। ক্রোম 56-এ আমরা ডিফল্টভাবে স্পর্শ শ্রোতাদের প্যাসিভ করার জন্য ডিফল্ট করছি যেখানে এটি প্রায়শই বিকাশকারীর উদ্দেশ্যের সাথে মেলে। আমরা বিশ্বাস করি যে এটি করার মাধ্যমে আমরা সাইটগুলিতে ন্যূনতম নেতিবাচক প্রভাব রেখে ব্যবহারকারীর অভিজ্ঞতাকে ব্যাপকভাবে উন্নত করতে পারি।

বিরল ক্ষেত্রে এই পরিবর্তনের ফলে অনিচ্ছাকৃত স্ক্রোলিং হতে পারে। এটি সাধারণত স্পর্শ-অ্যাকশন প্রয়োগ করে সহজে মোকাবেলা করা হয়: উপাদানটিতে কোন শৈলী নেই যেখানে স্ক্রোলিং হওয়া উচিত নয়। বিশদ বিবরণের জন্য পড়ুন, আপনি প্রভাবিত হলে কীভাবে জানবেন এবং আপনি এটি সম্পর্কে কী করতে পারেন।

পটভূমি: বাতিলযোগ্য ইভেন্টগুলি আপনার পৃষ্ঠাকে ধীর করে দেয়

আপনি যদি touchstart বা প্রথম touchmove ইভেন্টে preventDefault() কল করেন তাহলে আপনি স্ক্রোলিং প্রতিরোধ করবেন। সমস্যাটি হল যে প্রায়শই শ্রোতারা preventDefault() কল করবেন না, তবে ব্রাউজারটিকে নিশ্চিত হতে ইভেন্টটি শেষ হওয়ার জন্য অপেক্ষা করতে হবে। বিকাশকারী-সংজ্ঞায়িত "প্যাসিভ ইভেন্ট শ্রোতারা" এটি সমাধান করে। আপনি যখন আপনার ইভেন্ট হ্যান্ডলারে তৃতীয় প্যারামিটার হিসাবে একটি {passive: true} অবজেক্টের সাথে একটি স্পর্শ ইভেন্ট যুক্ত করেন তখন আপনি ব্রাউজারকে বলছেন যে touchstart লিসেনার preventDefault() কল করবে না এবং ব্রাউজারটি ব্লক না করে নিরাপদে স্ক্রোল করতে পারে শ্রোতা উদাহরণ স্বরূপ:

window.addEventListener("touchstart", func, {passive: true} );

হস্তক্ষেপ

ব্যবহারকারীর স্ক্রীন স্পর্শ করার পরে ডিসপ্লে আপডেট করতে যে সময় লাগে তা হ্রাস করাই আমাদের মূল প্রেরণা। টাচস্টার্ট এবং টাচমুভের ব্যবহার বোঝার জন্য আমরা কত ঘন ঘন স্ক্রোল ব্লকিং আচরণ ঘটেছে তা নির্ধারণ করতে মেট্রিক্স যোগ করেছি।

আমরা বাতিলযোগ্য টাচ ইভেন্টের শতাংশ দেখেছি যেগুলি একটি রুট টার্গেটে (উইন্ডো, ডকুমেন্ট, বা বডি) পাঠানো হয়েছিল এবং নির্ধারণ করেছি যে এই শ্রোতাদের প্রায় 80% ধারণাগতভাবে প্যাসিভ কিন্তু সেভাবে নিবন্ধিত হয়নি। এই সমস্যাটির স্কেল দেওয়ায় আমরা এই ইভেন্টগুলিকে স্বয়ংক্রিয়ভাবে "প্যাসিভ" করে কোনো বিকাশকারী পদক্ষেপ ছাড়াই স্ক্রলিং উন্নত করার একটি দুর্দান্ত সুযোগ লক্ষ্য করেছি।

এটি আমাদের হস্তক্ষেপকে এইভাবে সংজ্ঞায়িত করতে চালিত করেছে: যদি টাচস্টার্ট বা টাচমুভ শ্রোতার টার্গেট হয় window , document বা body আমরা ডিফল্ট passive থেকে true । এর মানে হল যে কোড যেমন:

window.addEventListener("touchstart", func);

এর সমতুল্য হয়ে ওঠে:

window.addEventListener("touchstart", func, {passive: true} );

এখন শ্রোতার ভিতরে preventDefault() জন্য কলগুলি উপেক্ষা করা হবে।

নীচের গ্রাফটি দেখায় যে স্ক্রোলগুলির শীর্ষ 1% দ্বারা একজন ব্যবহারকারী স্ক্রল স্পর্শ করার সময় থেকে ডিসপ্লে আপডেট হওয়ার সময় পর্যন্ত স্ক্রোল করার সময়। এই ডেটা Android এর জন্য Chrome-এর সমস্ত ওয়েবসাইটের জন্য। হস্তক্ষেপ সক্ষম হওয়ার আগে 1% স্ক্রোল মাত্র 400ms এর বেশি সময় নেয়। এটি এখন ক্রোম 56 বিটাতে মাত্র 250 মিলিমিটারে কমে গেছে; প্রায় 38% হ্রাস। ভবিষ্যতে আমরা সকল touchstart এবং touchmove শ্রোতাদের জন্য প্যাসিভ ট্রু ডিফল্ট করার আশা করি, এটিকে 50ms এর নিচে কমিয়ে আনব।

শীর্ষ 1% স্ক্রল বার গ্রাফ

ব্রেকেজ এবং গাইডেন্স

বেশিরভাগ ক্ষেত্রে, কোন ভাঙ্গন পরিলক্ষিত হবে না। কিন্তু যখন ভাঙ্গন দেখা দেয়, তখন সবচেয়ে সাধারণ লক্ষণ হল যে আপনি না চাইলে স্ক্রলিং ঘটে। বিরল ক্ষেত্রে, বিকাশকারীরা অপ্রত্যাশিত ক্লিক ইভেন্টগুলিও লক্ষ্য করতে পারে (যখন preventDefault() touchend লিসেনার থেকে অনুপস্থিত ছিল)।

Chrome 56 এবং পরবর্তীতে, হস্তক্ষেপ সক্রিয় থাকে এমন একটি ইভেন্টে আপনি preventDefault() কল করলে DevTools একটি সতর্কতা লগ করবে।

touch-passive.html:19 Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080

আপনার অ্যাপ্লিকেশানটি নির্ধারণ করতে পারে যে এটি বন্যভাবে এটিকে আঘাত করছে কিনা তা পরীক্ষা করে preventDefault defaultPrevented সম্পত্তির মাধ্যমে কল করার কোনো প্রভাব আছে কিনা।

আমরা দেখেছি যে যখনই সম্ভব স্পর্শ-অ্যাকশন CSS প্রপার্টি প্রয়োগ করে প্রভাবিত পৃষ্ঠাগুলির একটি বড় সংখ্যাগরিষ্ঠ অংশ তুলনামূলকভাবে সহজে সংশোধন করা হয়। আপনি যদি একটি উপাদানের মধ্যে সমস্ত ব্রাউজার স্ক্রলিং এবং জুমিং প্রতিরোধ করতে চান touch-action: none । আপনার যদি একটি অনুভূমিক ক্যারোজেল থাকে touch-action: pan-y pinch-zoom যাতে ব্যবহারকারী এখনও উল্লম্বভাবে স্ক্রোল করতে পারে এবং স্বাভাবিক হিসাবে জুম করতে পারে। টাচ ইভেন্ট নয়, পয়েন্টার ইভেন্ট সমর্থন করে এমন ডেস্কটপ এজ-এর মতো ব্রাউজারগুলিতে টাচ-অ্যাকশন সঠিকভাবে প্রয়োগ করা ইতিমধ্যেই প্রয়োজনীয়। মোবাইল Safari এবং পুরানো মোবাইল ব্রাউজারগুলির জন্য যা স্পর্শ-অ্যাকশন সমর্থন করে না আপনার স্পর্শ শ্রোতাদের অবশ্যই preventDefault কল করা চালিয়ে যেতে হবে এমনকি যখন এটি Chrome দ্বারা উপেক্ষা করা হবে।

আরও জটিল ক্ষেত্রে নিম্নলিখিতগুলির মধ্যে একটির উপর নির্ভর করা প্রয়োজন হতে পারে:

  • আপনার touchstart শ্রোতা যদি preventDefault() কল করে, তাহলে নিশ্চিত করুন যে ক্লিক ইভেন্টের জেনারেশন এবং অন্যান্য ডিফল্ট ট্যাপ আচরণকে দমন করার জন্য সংশ্লিষ্ট টাচএন্ড শ্রোতাদের কাছ থেকে preventDefault() কল করা হয়েছে।
  • শেষ (এবং নিরুৎসাহিত) ডিফল্ট আচরণ ওভাররাইড করতে addEventListener() এ {passive: false} পাস করুন। ব্যবহারকারী এজেন্ট EventListenerOptions সমর্থন করে কিনা তা শনাক্ত করতে হবে।

উপসংহার

Chrome 56-এ স্ক্রোলিং অনেক ওয়েবসাইটে যথেষ্ট দ্রুত শুরু হয়। এই পরিবর্তনের ফলে বেশিরভাগ ডেভেলপাররা লক্ষ্য করবেন এটাই একমাত্র প্রভাব। কিছু ক্ষেত্রে বিকাশকারীরা অনিচ্ছাকৃত স্ক্রোলিং লক্ষ্য করতে পারে।

যদিও মোবাইল সাফারির জন্য এটি করা এখনও প্রয়োজনীয়, ওয়েবসাইটগুলিকে touchstart এবং touchmove শ্রোতাদের ভিতরে preventDefault() কল করার উপর নির্ভর করা উচিত নয় কারণ এটি আর Chrome-এ সম্মানিত হওয়ার নিশ্চয়তা দেয় না। বিকাশকারীদের এমন উপাদানগুলিতে touch-action CSS বৈশিষ্ট্য প্রয়োগ করা উচিত যেখানে কোনও স্পর্শ ইভেন্ট হওয়ার আগে ব্রাউজারকে অবহিত করতে স্ক্রলিং এবং জুমিং অক্ষম করা উচিত। একটি ট্যাপের ডিফল্ট আচরণকে দমন করতে (যেমন একটি ক্লিক ইভেন্টের প্রজন্ম), একটি touchend লিসেনারের ভিতরে preventDefault() কল করুন।