সামনের পথ নির্দেশ করে

Sérgio Gomes

ওয়েবে জিনিসের দিকে ইঙ্গিত করা সহজ ছিল। আপনার কাছে একটি মাউস ছিল, আপনি এটিকে ঘুরিয়েছেন, কখনও কখনও আপনি বোতামগুলি পুশ করেছেন এবং এটিই ছিল। মাউস নয় এমন সবকিছুই এক হিসাবে অনুকরণ করা হয়েছিল এবং বিকাশকারীরা ঠিক কীসের উপর নির্ভর করতে হবে তা জানত।

যদিও সহজ মানে ভালো মানে না। সময়ের সাথে সাথে, এটি ক্রমবর্ধমানভাবে গুরুত্বপূর্ণ হয়ে ওঠে যে সবকিছুই একটি ইঁদুর ছিল না (বা ভান করা হয়): আশ্চর্যজনক সৃজনশীল স্বাধীনতার জন্য আপনার চাপ-সংবেদনশীল এবং কাত-সচেতন কলম থাকতে পারে; আপনি আপনার আঙ্গুলগুলি ব্যবহার করতে পারেন, তাই আপনার যা প্রয়োজন তা হল ডিভাইস এবং আপনার হাত; এবং আরে, কেন আপনি এটিতে থাকাকালীন একাধিক আঙুল ব্যবহার করবেন না?

এতে আমাদের সাহায্য করার জন্য আমরা কিছু সময়ের জন্য স্পর্শ ইভেন্ট করেছি, কিন্তু সেগুলি বিশেষভাবে স্পর্শের জন্য একটি সম্পূর্ণ আলাদা API, আপনি যদি মাউস এবং স্পর্শ উভয়কেই সমর্থন করতে চান তবে আপনাকে দুটি পৃথক ইভেন্ট মডেল কোড করতে বাধ্য করে৷ Chrome 55 একটি নতুন স্ট্যান্ডার্ডের সাথে প্রেরণ করে যা উভয় মডেলকে একীভূত করে: পয়েন্টার ইভেন্ট।

একটি একক ইভেন্ট মডেল

পয়েন্টার ইভেন্টগুলি ব্রাউজারের জন্য পয়েন্টার ইনপুট মডেলকে একীভূত করে, স্পর্শ, কলম এবং ইঁদুরকে ইভেন্টের একক সেটে একত্রিত করে। উদাহরণ স্বরূপ:

document.addEventListener('pointermove',
    ev => console.log('The pointer moved.'));
foo.addEventListener('pointerover',
    ev => console.log('The pointer is now over foo.'));

এখানে সমস্ত উপলব্ধ ইভেন্টগুলির একটি তালিকা রয়েছে, যা আপনি মাউস ইভেন্টগুলির সাথে পরিচিত হলে বেশ পরিচিত দেখা উচিত:

pointerover পয়েন্টারটি উপাদানটির বাউন্ডিং বাক্সে প্রবেশ করেছে। এটি হোভার সমর্থন করে এমন ডিভাইসগুলির জন্য অবিলম্বে ঘটবে, বা এমন ডিভাইসগুলির জন্য একটি pointerdown ইভেন্টের আগে যা করে না।
pointerenter pointerover মতো, কিন্তু বুদবুদ করে না এবং বংশধরদের ভিন্নভাবে পরিচালনা করে। বিশদ বিবরণ .
pointerdown ইনপুট ডিভাইসের শব্দার্থবিদ্যার উপর নির্ভর করে পয়েন্টারটি সক্রিয় বোতাম অবস্থায় প্রবেশ করেছে, হয় একটি বোতাম টিপে বা যোগাযোগ স্থাপন করা হচ্ছে।
pointermove পয়েন্টার অবস্থান পরিবর্তন হয়েছে.
pointerup পয়েন্টার সক্রিয় বোতাম অবস্থা ছেড়ে গেছে.
pointercancel এমন কিছু ঘটেছে যার মানে এটি অসম্ভাব্য যে পয়েন্টারটি আর কোনো ইভেন্ট নির্গত করবে। এর মানে হল আপনার যেকোনও অগ্রগতি ক্রিয়া বাতিল করা উচিত এবং একটি নিরপেক্ষ ইনপুট অবস্থায় ফিরে যাওয়া উচিত।
pointerout পয়েন্টার উপাদান বা পর্দার বাউন্ডিং বক্স ছেড়ে গেছে। এছাড়াও একটি pointerup পরে, যদি ডিভাইসটি হোভার সমর্থন না করে।
pointerleave pointerout মতো, কিন্তু বুদ্বুদ করে না এবং বংশধরদের ভিন্নভাবে পরিচালনা করে। বিশদ বিবরণ .
gotpointercapture এলিমেন্ট পয়েন্টার ক্যাপচার পেয়েছে।
lostpointercapture যে পয়েন্টারটি বন্দী করা হয়েছিল তা ছেড়ে দেওয়া হয়েছে।

বিভিন্ন ধরনের ইনপুট

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

switch(ev.pointerType) {
    case 'mouse':
    // Do nothing.
    break;
    case 'touch':
    // Allow drag gesture.
    break;
    case 'pen':
    // Also allow drag gesture.
    break;
    default:
    // Getting an empty string means the browser doesn't know
    // what device type it is. Let's assume mouse and do nothing.
    break;
}

ডিফল্ট অ্যাকশন

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

পয়েন্টার ইভেন্টগুলির সাথে, যখনই স্ক্রোল বা জুমের মতো একটি ডিফল্ট অ্যাকশন ট্রিগার হয়, আপনি একটি pointercancel ইভেন্ট পাবেন, যাতে আপনাকে জানানো হয় যে ব্রাউজার পয়েন্টারের নিয়ন্ত্রণ নিয়েছে। উদাহরণ স্বরূপ:

document.addEventListener('pointercancel',
    ev => console.log('Go home, the browser is in charge now.'));

অন্তর্নির্মিত গতি : এই মডেলটি স্পর্শ ইভেন্টের তুলনায় ডিফল্টভাবে আরও ভাল পারফরম্যান্সের জন্য অনুমতি দেয়, যেখানে আপনাকে একই স্তরের প্রতিক্রিয়াশীলতা অর্জন করতে প্যাসিভ ইভেন্ট শ্রোতাদের ব্যবহার করতে হবে।

আপনি touch-action CSS প্রপার্টি দিয়ে ব্রাউজারকে নিয়ন্ত্রণ নেওয়া থেকে থামাতে পারেন। একটি উপাদানে এটিকে none সেট করা হলে সেই উপাদানটির উপর শুরু হওয়া সমস্ত ব্রাউজার-সংজ্ঞায়িত ক্রিয়াগুলি অক্ষম হবে৷ কিন্তু সূক্ষ্ম-দানাযুক্ত নিয়ন্ত্রণের জন্য আরও অনেকগুলি মান রয়েছে, যেমন pan-x , ব্রাউজারকে x অক্ষে চলাচলে প্রতিক্রিয়া দেখাতে দেয় কিন্তু y অক্ষে নয়। Chrome 55 নিম্নলিখিত মানগুলিকে সমর্থন করে:

auto ডিফল্ট; ব্রাউজার যেকোনো ডিফল্ট ক্রিয়া সম্পাদন করতে পারে।
none ব্রাউজারকে কোনো ডিফল্ট ক্রিয়া সম্পাদন করার অনুমতি দেওয়া হয় না।
pan-x ব্রাউজারটিকে শুধুমাত্র অনুভূমিক স্ক্রোল ডিফল্ট ক্রিয়া সম্পাদন করার অনুমতি দেওয়া হয়।
pan-y ব্রাউজারটিকে শুধুমাত্র উল্লম্ব স্ক্রোল ডিফল্ট ক্রিয়া সম্পাদন করার অনুমতি দেওয়া হয়।
pan-left ব্রাউজারটিকে শুধুমাত্র অনুভূমিক স্ক্রোল ডিফল্ট ক্রিয়া সম্পাদন করার অনুমতি দেওয়া হয় এবং শুধুমাত্র বাম দিকে পৃষ্ঠাটি প্যান করার জন্য।
pan-right ব্রাউজারটিকে শুধুমাত্র অনুভূমিক স্ক্রোল ডিফল্ট ক্রিয়া সম্পাদন করার অনুমতি দেওয়া হয় এবং শুধুমাত্র ডানদিকে পৃষ্ঠাটি প্যান করার জন্য।
pan-up ব্রাউজারটিকে শুধুমাত্র উল্লম্ব স্ক্রোল ডিফল্ট ক্রিয়া সম্পাদন করার অনুমতি দেওয়া হয় এবং শুধুমাত্র পৃষ্ঠাটি প্যান আপ করার জন্য।
pan-down ব্রাউজারটিকে শুধুমাত্র উল্লম্ব স্ক্রোল ডিফল্ট ক্রিয়া সম্পাদন করার অনুমতি দেওয়া হয় এবং শুধুমাত্র পৃষ্ঠাটি নীচে প্যান করার জন্য।
manipulation ব্রাউজারটিকে শুধুমাত্র স্ক্রোল এবং জুম অ্যাকশন করার অনুমতি দেওয়া হয়।

পয়েন্টার ক্যাপচার

একটি ভাঙা mouseup ইভেন্ট ডিবাগ করার জন্য কখনও হতাশাজনক ঘন্টা কাটিয়েছেন, যতক্ষণ না আপনি বুঝতে পারেন যে ব্যবহারকারী আপনার ক্লিক লক্ষ্যের বাইরের বোতামটি ছেড়ে দিচ্ছেন? না? ঠিক আছে, হয়তো এটা শুধু আমি, তারপর.

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

পয়েন্টার ইভেন্টগুলির সাথে একটি আরও ভাল সমাধান আসে: আপনি পয়েন্টারটি ক্যাপচার করতে পারেন, যাতে আপনি সেই pointerup ইভেন্টটি (বা এর অন্য কোনও অধরা বন্ধু) পেতে পারেন।

const foo = document.querySelector('#foo');
foo.addEventListener('pointerdown', ev => {
    console.log('Button down, capturing!');
    // Every pointer has an ID, which you can read from the event.
    foo.setPointerCapture(ev.pointerId);
});

foo.addEventListener('pointerup', 
    ev => console.log('Button up. Every time!'));

ব্রাউজার সমর্থন

লেখার সময়, পয়েন্টার ইভেন্টগুলি ইন্টারনেট এক্সপ্লোরার 11, মাইক্রোসফ্ট এজ, ক্রোম এবং অপেরায় সমর্থিত এবং ফায়ারফক্সে আংশিকভাবে সমর্থিত। আপনি caniuse.com এ একটি আপ-টু-ডেট তালিকা পেতে পারেন।

শূন্যস্থান পূরণের জন্য আপনি পয়েন্টার ইভেন্ট পলিফিল ব্যবহার করতে পারেন। বিকল্পভাবে, রানটাইমে ব্রাউজার সমর্থনের জন্য পরীক্ষা করা সোজা:

if (window.PointerEvent) {
    // Yay, we can use pointer events!
} else {
    // Back to mouse and touch events, I guess.
}

পয়েন্টার ইভেন্টগুলি প্রগতিশীল বর্ধনের জন্য একটি দুর্দান্ত প্রার্থী: উপরের চেকটি করতে আপনার প্রাথমিক পদ্ধতিগুলিকে সংশোধন করুন, if ব্লকে পয়েন্টার ইভেন্ট হ্যান্ডলার যুক্ত করুন এবং আপনার মাউস/টাচ ইভেন্ট হ্যান্ডলারকে else ব্লকে নিয়ে যান।

তাই এগিয়ে যান, তাদের একটি স্পিন দিন এবং আপনি কি মনে করেন তা আমাদের জানান!