diff --git a/README.md b/README.md index b7110b8..14dc3b7 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 diff --git a/package-lock.json b/package-lock.json index 547117e..d047129 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { - "name": "@xata.io/take-screenshot", + "name": "@xata.io/screenshot", "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "@xata.io/take-screenshot", + "name": "@xata.io/screenshot", "version": "1.0.0", - "license": "ISC", + "license": "MIT", "devDependencies": { "@rollup/plugin-commonjs": "^21.0.1", "@rollup/plugin-node-resolve": "^13.1.3", diff --git a/src/paintVideoFrameOnCanvas.ts b/src/paintVideoFrameOnCanvas.ts index f551c0c..c81c710 100644 --- a/src/paintVideoFrameOnCanvas.ts +++ b/src/paintVideoFrameOnCanvas.ts @@ -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; }; diff --git a/src/takeScreenshot.ts b/src/takeScreenshot.ts index 59e12c6..27b71af 100644 --- a/src/takeScreenshot.ts +++ b/src/takeScreenshot.ts @@ -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; }; /** @@ -44,6 +50,7 @@ export const takeScreenshot = async ({ quality = 0.7, type = "image/jpeg", soundEffectUrl, + element, }: Options = {}) => { await onCaptureStart?.(); return navigator.mediaDevices @@ -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);