← Back toDrag and drop in React

Take a screenshot of a portion of an element

Written byPhuoc Nguyen
Created
14 Nov, 2023
Last updated
15 Nov, 2023
There are many situations where taking a screenshot can be incredibly useful. For example, if you encounter an issue with a website or application, taking a screenshot can help you provide more detailed information to the developer. They may ask for a screenshot to better understand what's going on and how to fix it.
Another example is when you're working with a designer or developer. Taking screenshots and annotating them can be incredibly helpful in providing feedback. You can point out specific elements that need to be changed or suggest new ideas.
Sometimes, you might come across important information online that you want to save for later. Taking a screenshot can be an easy way to do so. You can also use screenshots to capture receipts, confirmation pages, or other important documents.
Lastly, taking screenshots can help you show someone how to do something on your computer. By creating step-by-step instructions using annotated screenshots, you can make the process much clearer.
In this post, we'll learn how to take a screenshot of a portion of an element with React.

Selecting a portion of an element

In our previous post, we learned that users can select a portion of an element by holding down the mouse button and dragging it across the screen. To make this process even easier, we created a custom hook called `useClickToSelect`.
Using the hook is a breeze. It returns an array of six items that you can use to customize and enhance your element selection.
ts
const [clickToSelectRef, dx, dy, startX, startY, selection] = useClickToSelect();
The first thing we need to do is reference the target element so that we can enable click-and-drag functionality. To do this, we'll attach the reference to the target element using the `ref` attribute.
tsx
<div className="container" ref={clickToSelectRef}>
...
</div>
You can use the following items to generate a preview of a selected portion: `dx` and `dy` to set the width and height of the selection, and `startX` and `startY` to indicate its position.
It's important to note that the selection only appears after users release the mouse following a click-and-drag action. To figure this out, simply check if the `selection` state is `Selection.Dragging`.
tsx
{
selection === Selection.Dragging && (
<div
className="selection"
style={{
transform: `translate(${startX}px, ${startY}px)`,
width: `${dx}px`,
height: `${dy}px`,
}}
/>
)
}

Saving the selection as an image

To save a screenshot of a selected portion as an image, you can use the html2canvas library. To get started, simply install the `html2canvas` library using npm.
console
$ npm install html2canvas --save
Next, we can import it into our component.
ts
import html2canvas from "html2canvas";
After installing and importing the library, we can use the `html2canvas` function to create a canvas element from our selected portion. To do this, we'll need to provide the container that holds our selection, along with the coordinates and dimensions of the selection.
ts
html2canvas(container, {
x: startX,
y: startY,
width: w,
height: h,
}).then((canvas) => {
...
});
The `html2canvas` function gives us a Promise that resolves to a canvas element. We can take this canvas and turn it into an image by using its `toDataURL()` method.
ts
const img = canvas.toDataURL("image/png");
To get a PNG image that we can use however we like, we first need to encode it in base64. Once we have the encoded image, we can allow users to download it as an image file. To do this, we'll create an anchor tag (`<a>`) and set its `href` attribute to the data URL of our image. We'll also set its `download` attribute to specify the filename of the downloaded file.
ts
const link = document.createElement("a");
link.href = img;
link.download = "screenshot.png";
Lastly, we'll add the anchor tag to the document body, programmatically trigger a click event on it using `.click()`, and once it's done, we'll remove it from the DOM.
ts
document.body.appendChild(link);
link.click();
link.remove();
So, when does the screenshot saving happen? It happens right after the user releases the mouse. To make this happen, we can use the `useEffect` hook to watch for changes in the states related to the selection and trigger the saving of a screenshot.
Here's how we set it up: we'll use an `useEffect` hook that watches for changes in the `dx`, `dy`, `startX`, `startY`, and `selected` states. Once any of these values are updated, we check if all the conditions are met to save a screenshot.
If the container reference is not null, and if the selection is in a `Selected` state, and if both the width (`dx`) and height (`dy`) of the selection are greater than zero, we initiate the process of taking a screenshot. It's that simple!
ts
React.useEffect(() => {
const container = containerRef.current;
if (!container || selection !== Selection.Selected || dx === 0 || dy === 0) {
return;
}
// Save the screenshot ...
}, [dx, dy, startX, startY, selection]);
With our latest update, users no longer need to trigger a separate action to save their selected portion as an image. It happens automatically once they release their mouse button after selecting the desired area.
Want to see it in action? Give our demo a try! Just click and drag your mouse to generate a screenshot of the selected area. It's that easy!

Conclusion

To sum up, taking screenshots can be a useful tool in many situations. Whether you need to report an error, give feedback on a design, capture important information, or teach someone how to do something, screenshots can make the process clearer and more efficient. With the `useClickToSelect` hook and the `html2canvas` library, you can easily capture and save selected portions of an element with React as images. This feature can come in handy in various scenarios where you need to save or share specific parts of an element.

See also

If you found this post helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

Questions? 🙋

Do you have any questions about front-end development? If so, feel free to create a new issue on GitHub using the button below. I'm happy to help with any topic you'd like to learn more about, even beyond what's covered in this post.
While I have a long list of upcoming topics, I'm always eager to prioritize your questions and ideas for future content. Let's learn and grow together! Sharing knowledge is the best way to elevate ourselves 🥷.
Ask me questions

Recent posts ⚡

Newsletter 🔔

If you're into front-end technologies and you want to see more of the content I'm creating, then you might want to consider subscribing to my newsletter.
By subscribing, you'll be the first to know about new articles, products, and exclusive promotions.
Don't worry, I won't spam you. And if you ever change your mind, you can unsubscribe at any time.
Phước Nguyễn