
We know that browsers work with the help of JavaScript, i.e. every browser has a JavaScript engine to execute the code to present the final web page. When writing code for the Web, there are a large number of Web APIs available. Today, we will understand how the pointer capture API works.Here is the list of all the APIs you may be able to use while developing a web application.
Introduction to Pointer Events
A decade ago, if you would have asked me to give an example of the pointer, I would have referred to the cursor pointer of a computer that is accessed through a mouse.
However, with the invention of touch-based devices and their support for the web, touch events were introduced as a part of web APIs. These touch events provided a similar behavior as that of the pointer event. Since then, many devices supported other types of pointing input devices, such as pen/stylus and touch surfaces, and extensions to the existing pointing device event models were needed.
According to the official documentation -
Pointer events are DOM events that are fired for a pointing device. They are designed to create a single DOM event model to handle pointing input devices such as a mouse, pen/stylus or touch (such as one or more fingers).
Thepointer is a hardware-agnostic device that can target a specific set of screen coordinates. Thus, pointers can simplify creating web applications by providing a good user experience, regardless of the user's hardware.
Types of pointer events
Pointer events contain the usual properties of mouse events (client coordinates, target element, button states, etc.) in addition to new properties for other forms of input: pressure, contact geometry, tilt, etc.
Pointer event | Similar mouse event |
---|---|
pointerdown | mousedown |
pointerup | mouseup |
pointermove | mousemove |
pointerover | mouseover |
pointerout | mouseout |
pointerenter | mouseenter |
pointerleave | mouseleave |
pointercancel | - |
gotpointercapture | - |
lostpointercapture | - |
In fact, thePointerEvent
interface inherits all of theMouseEvent
properties, thus facilitating the migration of content from mouse events to pointer events.
You can refer toMDN Docs to learn in detail about the above-mentioned events. In this blog, we are going to focus on one of the special features of pointer events.
Pointer Capture Event
Pointer capture allows the events for a pointer to be retargeted to a particular element other than the normal hit test result of the pointer's location.
The idea is very simple but may seem quite odd at first, as nothing like that exists for any other event type. We will learn this concept with a simple example. When I learnt about pointer capture events using this example, I was amazed by the simplicity it provides to the end users! Thus, I wanted to share this with a wider audience😀.
I'm sure most of you would have watched youtube videos on your phone. While watching, if you wanted to seek a particular timestamp, all you need to do is simply drag thered dot
on the timeline and move to the appropriate timestamp value. The next time you perform this activity, observe if you are always touching thered dot
. Most of the time, you would have touched thered dot
but moved away from this target element. That's exactly where"Pointer Capture Event" comes into the picture.
You can test the demo of pointer capture onhttps://webapis-playground.vercel.app/demo/pointer-capture
I built this feature as one of my early contributions to theopen source software (OSS).
Let's understand how the code works!
For the above example, I have used React and Tailwind. I have kept thepointer event
functionality in a separate JavaScript module since the application is mainly focusing on Web APIs.
JavaScript File:https://github.com/atapas/webapis-playground/blob/master/src/modules/apis/pointer-capture/index.ts
React File:https://github.com/atapas/webapis-playground/blob/master/src/modules/demos/pointer-capture/index.tsx
The main elements to focus the React file are:
<divid="gray-timeline"className="tw-h-5 tw-w-full tw-bg-gray-400 tw-mb-5 tw-flex tw-items-center tw-relative tw-cursor-pointer"style={{touchAction:isCapture?'none':'auto'}}onPointerUp={e=>run.onPointerUp(e,isCapture)}onPointerDown={e=>run.onPointerDown(e,isCapture)}onPointerMove={run.onPointerMove}><divid="red-timeline"className="tw-relative tw-bg-red-600 tw-h-full tw-rounded-r-full tw-w-7"><divid="red-dot"className="tw-absolute tw-bg-red-700 tw-h-7 tw-w-7 tw-rounded-full tw--top-1 tw-left-4"></div></div>
The main div container with theid="gray-timeline"
has 3 events attached:
onPointerDown
to start capturing the pointer eventonPointerMove
to accurately provide the motion of the captured event (red dot
) even though thetouch pointer
is not within the target elementonPointerUp
to stop capturing the pointer event
By adding the pointer events on the parent container, theid="red-timeline"
andid="red-dot"
would work smoothly to capture and end the pointer event's behavior.
I have also added a react stateisCapture
. This would ensure that the pointer event is "captured" only whenisCapture=true
. You can set this value to false by toggling the switch to "Turn off".
Moving on, let's understand the behavior defined through these attached events.
letflag=false;functiononPointerDown(event:React.PointerEvent<Element>,isCapture:boolean){consttimeline=document.querySelector('#red-timeline')asHTMLElement;if(isCapture){timeline.setPointerCapture(event.pointerId);}flag=true;onPointerMove(event);}
I am using a global variableflag
to identify if the pointer is under capture. In theonPointerDown
function, we find the target element i.e. thered-timeline
element which needs to be captured. Based on theisCapture
state value, we start capturing the pointer within this element by invoking thesetPointerCapture
.
setPointerCapture
takes one parameter which is thepointerId
of the given pointer event.
functiononPointerMove(event:React.PointerEvent<Element>){consttimeline=document.querySelector('#red-timeline')asHTMLElement;if(flag){constrect=timeline.getBoundingClientRect();timeline.style.width=`${event.clientX-rect.left}px`;constchildTag=document.querySelector('#dot')asHTMLElement;childTag.style.left=`${event.clientX-rect.left-20}px`;}}
Once theonPointerDown
is fired and the pointer event is captured, as I start moving the pointer across the screen, theonPointerMove
event is fired. In this function, we are capturing the latest value of the pointer and set the style attributes of the timeline element. It is because of this function you are able to see a smooth transition of the red timeline getting updated along with the movement of thered-dot
.
functiononPointerUp(event:React.PointerEvent<Element>,isCapture:boolean){consttimeline=document.querySelector('#red-timeline')asHTMLElement;if(isCapture){timeline.releasePointerCapture(event.pointerId);}flag=false;}
TheonPointerUp
event is fired when we stop moving the "red dot" and release the touch (or click). At this moment, we release the pointer capture event and fireonPointerUp
function. Here, we invokereleasePointerCapture
to stop capturing the event any further.
Link to the demo application
You can test the demo of pointer capture onhttps://webapis-playground.vercel.app/demo/pointer-capture
Check out the demo of other Web APIs athttps://webapis-playground.vercel.app/
If you learnt something new today and found this article exciting, go ahead and give this post a like!
Feel free to reach out to me on [Twitter](https://twitter.com/supminn) if you have any queries.
Peace ✌️
Top comments(1)

- Email
- LocationBangalore
- PronounsHe, Him
- WorkEducator @tapaScript
- Joined
Very nice.
For further actions, you may consider blocking this person and/orreporting abuse