Как сделать скриншот веб-страницы, используя html5, без рендеринга на холсте через JS - PullRequest
2 голосов
/ 02 апреля 2019

Важная часть - сделать снимок экрана

  • точно , поскольку пользователь видит окно браузера. Это исключает canvas - на основе вопросов и ответов, которые эмулируют браузер, но не могут точно воспроизвести, как он отображает html и css
  • без каких-либо нестандартных плагинов за пределами простого, совместимого со стандартами html5 и JS . Это исключает Java-апплеты, Flash, ActiveX и любезно просит пользователя нажать кнопку «печать экрана», чтобы затем вставить изображение в форму.

Я натолкнулся на несколько вопросов о стековом потоке, касающихся этого (см. Выше), но не нашел ответа, который удовлетворял бы обоим условиям. Вместо того, чтобы пытаться добавить частичный ответ на существующие вопросы с немного другими требованиями, я задаю этот вопрос в отдельном вопросе.

До сих пор я нашел отличное объяснение того, как получать и передавать пиксели из любого окна в элемент video, используя API захвата экрана . Однако я пропускаю следующий шаг, где те пиксели, которые отображаются в видеоэлементе, преобразуются в файл jpg или png, который можно загрузить на сервер.

1 Ответ

1 голос
/ 02 апреля 2019

Это проще, чем казалось. Недостающая часть, сохраняющая стоп-кадр видео в png, может быть достигнута с кодом из этого ответа . Полный код будет следующим:

const v = document.getElementById("v");
const b = document.getElementById("b");
const i = document.getElementById("i");

navigator.mediaDevices.getDisplayMedia({
  audio: false
}).then((r) => {
  console.log(r);
  v.srcObject = r;
}).catch((e) => {
  console.log("this must be run in a secure context. Stack snippets (rightfully) refuse to run this.");
});

b.onclick = () => {
  // take screenshot
  // from https://stackoverflow.com/a/44325898/15472
  let scale = 1;

  const canvas = document.createElement("canvas");
  canvas.width = v.clientWidth * scale;
  canvas.height = v.clientHeight * scale;
  canvas.getContext('2d').drawImage(v, 0, 0,
    canvas.width, canvas.height);

  i.src = canvas.toDataURL();
  // you can send i.src here to a server

  // stop video
  let tracks = v.srcObject.getTracks();
  tracks.forEach(track => track.stop());
  v.srcObject = null;
}
#v,
#i {
  width: 400;
  height: 300;
}

#v {
  border: 1px solid blue;
}

#i {
  border: 1px solid green;
}
<div>
  <video id="v" autoplay></video>
  <button id="b">take screenshot</button>
  <img id="i" src="//:0" />
</div>

Обратите внимание, что StackOverflow не позволяет запрашивать разрешения захвата экрана, и поэтому этот код здесь не запускается.

...