Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This tool uses [native browser APIs](https://developer.mozilla.org/en-US/docs/We
Pick your preference. You can easily learn about this project in the following ways:

- Watch an explainer on [YouTube](https://www.youtube.com/watch?v=uC6RbWanoy4).
- See it in action on [StackBlitz](https://stackblitz.com/edit/node-b86qqd?file=app/routes/index.tsx). You'll need to open the preview in a new window to get around extra iframe security that StackBlitz needs.
- See it in action on [StackBlitz](https://stackblitz.com/edit/node-b86qqd?file=app/routes/index.tsx). You'll need to open the preview in a new window to get around extra iframe security that StackBlitz needs.
- Read about the details on the [Xata Blog](https://xata.io/blog/introducing-screenshot/).

## Usage
Expand Down Expand Up @@ -47,8 +47,11 @@ if (checkIfBrowserSupported()) {
| `quality` | The quality of the final image on a scale of 0 to 1. 0 is lowest quality, 1 is highest. | _nope_ | `.7` |
| `onCaptureStart` | An `async` function that does stuff when the capture starts. You'll usually want to hide any modals or anything here. | _nope_ | |
| `onCaptureEnd` | An `async` function that does stuff after capture ends. This is usually when you'll want to clean up. | _nope_ | |
| `type` | What kind of image do we want? Possible values are `"image/jpeg"`, `"image/png"` and `"image/webp"`. | _nope_ | `"image/jpeg"` |
| `type` | What kind of image do we want? Possible values are `"image/jpeg"`, `"image/png"` and `"image/webp"`. | _nope_ | `"image/jpeg"` |
| `soundEffectURL` | Why not play a little camera click sound effect when taking a screenshot? | _nope_ | - |
| `element` | Do you want to crop out a specific element from the DOM? Pass it in here. | _nope_ | - |

Please note that when passing an `element` to be cropped, the console should be closed to get a perfect positioning.

## Contributing

Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions src/paintVideoFrameOnCanvas.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
export const paintVideoFrameOnCanvas = (video: HTMLVideoElement) => {
export const paintVideoFrameOnCanvas = (video: HTMLVideoElement, cropElement?: HTMLElement) => {
// Get the video settings
// @ts-ignore because getTracks is very much valid in modern browsers
const videoTrackSettings = video.srcObject?.getTracks()[0].getSettings();

// Create a canvas with the video's size and draw the video frame on it
const canvas = document.createElement("canvas");
canvas.width = videoTrackSettings?.width ?? 0;
canvas.height = videoTrackSettings?.height ?? 0;
const crop = cropElement?.getBoundingClientRect();
canvas.width = crop?.width ?? videoTrackSettings?.width ?? 0;
canvas.height = crop?.height ?? videoTrackSettings?.height ?? 0;
const ctx = canvas.getContext("2d");
ctx?.drawImage(video, 0, 0);
if (crop) {
const dpr = window.devicePixelRatio
ctx?.drawImage(video, crop.x * dpr, crop.y * dpr, crop.width * dpr, crop.height * dpr);
} else {
ctx?.drawImage(video, 0, 0);
}

return canvas;
};
9 changes: 8 additions & 1 deletion src/takeScreenshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ type Options = {
* @optional
*/
soundEffectUrl?: string;

/**
* Do you want to crop out a specific element from the DOM? Pass it in here.
* Note that the console should be closed to get perfect positioning.
*/
element?: HTMLElement;
};

/**
Expand All @@ -44,6 +50,7 @@ export const takeScreenshot = async ({
quality = 0.7,
type = "image/jpeg",
soundEffectUrl,
element,
}: Options = {}) => {
await onCaptureStart?.();
return navigator.mediaDevices
Expand Down Expand Up @@ -73,7 +80,7 @@ export const takeScreenshot = async ({
await sleep();

// Paint the video frame on a canvas...
const canvas = paintVideoFrameOnCanvas(video);
const canvas = paintVideoFrameOnCanvas(video, element);

// Set the data URL in state
const screenshot = canvas.toDataURL(type, quality);
Expand Down