Skip to content

Commit 39ce84b

Browse files
authored
Add an example for screenshotting with Element Capture (#399)
1 parent 0e0af89 commit 39ce84b

4 files changed

Lines changed: 99 additions & 0 deletions

File tree

‎screen-capture-api/README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
- [Screen Capture API example](https://mdn.github.io/dom-examples/screen-capture-api/basic-screen-capture): A basic example showing how to use the [Screen Capture API](https://developer.mozilla.org/docs/Web/API/Screen_Capture_API) to capture a surface (such as a window or tab) and broadcast the resulting stream in a `<video>` element.
44
- [Element Capture API example](https://mdn.github.io/dom-examples/screen-capture-api/element-capture): The same example, but this time using the [Element Capture API](https://developer.mozilla.org/docs/Web/API/Screen_Capture_extensions/Element_Region_Capture#the_element_capture_api) to restrict the broadcast stream to one particular rendered element inside the same tab the app is running in.
55
- [Region Capture API example](https://mdn.github.io/dom-examples/screen-capture-api/region-capture): The same example, but this time using the [Region Capture API](https://developer.mozilla.org/docs/Web/API/Screen_Capture_extensions/Element_Region_Capture#the_region_capture_api) to crop the broadcast stream to the screen area in which one particular element is rendered, inside the same tab the app is running in.
6+
- [Element Capture screenshot example](https://mdn.github.io/dom-examples/screen-capture-api/element-screenshot): Save a PNG of a rendered element in the current tab using Element Capture and `ImageCapture.grabFrame()`, without displaying or recording a video.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
* {
2+
box-sizing: border-box;
3+
}
4+
5+
body {
6+
padding: 0 25px;
7+
}
8+
9+
#demo {
10+
/* Forms a stacking context */
11+
isolation: isolate;
12+
/* Flattened */
13+
transform-style: flat;
14+
/* Explicit background color to stop the capture being transparent */
15+
background-color: white;
16+
}
17+
18+
#demo > h2 {
19+
margin-top: 0;
20+
}
21+
22+
#demo > p {
23+
border: 1px solid #ccc;
24+
margin: 0;
25+
padding: 5px;
26+
height: 320px;
27+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>Element Capture screenshot demo</title>
6+
<link href="index.css" rel="stylesheet" />
7+
<script defer src="index.js"></script>
8+
</head>
9+
10+
<body>
11+
<h1>Element Capture screenshot example</h1>
12+
<p>Click "Save screenshot" and select this tab in the browser's sharing dialog to download a PNG of the demo container below. This example uses the Screen Capture API, Element Capture API, and Image Capture API. Sharing stops after the screenshot is captured.</p>
13+
14+
<p>
15+
<button id="screenshot">Save screenshot</button>
16+
<a id="download" download="screenshot.png" hidden>Download screenshot</a>
17+
</p>
18+
19+
<div id="demo">
20+
<h2>Some kind of demo</h2>
21+
<p>This container is a placeholder for some kind of demo that you might want to save as a screenshot.</p>
22+
</div>
23+
</body>
24+
</html>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const screenshotElem = document.getElementById("screenshot");
2+
const downloadElem = document.getElementById("download");
3+
const demoElem = document.getElementById("demo");
4+
let screenshotURL;
5+
6+
screenshotElem.addEventListener("click", async () => {
7+
screenshotElem.disabled = true;
8+
let stream;
9+
let bitmap;
10+
11+
try {
12+
stream = await navigator.mediaDevices.getDisplayMedia({
13+
video: true,
14+
audio: false,
15+
preferCurrentTab: true,
16+
});
17+
const [track] = stream.getVideoTracks();
18+
const restrictionTarget = await RestrictionTarget.fromElement(demoElem);
19+
await track.restrictTo(restrictionTarget);
20+
bitmap = await new ImageCapture(track).grabFrame();
21+
22+
const canvas = document.createElement("canvas");
23+
canvas.width = bitmap.width;
24+
canvas.height = bitmap.height;
25+
canvas.getContext("2d").drawImage(bitmap, 0, 0);
26+
const blob = await new Promise((resolve) => {
27+
canvas.toBlob(resolve, "image/png");
28+
});
29+
if (!blob) {
30+
throw new Error("Could not create the screenshot.");
31+
}
32+
33+
if (screenshotURL) {
34+
URL.revokeObjectURL(screenshotURL);
35+
}
36+
screenshotURL = URL.createObjectURL(blob);
37+
downloadElem.href = screenshotURL;
38+
downloadElem.hidden = false;
39+
downloadElem.click();
40+
} catch (err) {
41+
console.error(err);
42+
} finally {
43+
stream?.getTracks().forEach((track) => track.stop());
44+
bitmap?.close();
45+
screenshotElem.disabled = false;
46+
}
47+
});

0 commit comments

Comments
 (0)