Google "Сообщить об ошибке" или "Инструмент обратной связи" позволяет вам выбрать область вашего окна браузера, чтобы создать скриншот, который отправляется с отзывами об ошибке.
Снимок экрана Джейсона Малого, размещенный в повторяющемся вопросе.Суб >
Как они это делают? API обратной связи Google JavaScript загружается из здесь и их обзор модуля обратной связи продемонстрирует возможность скриншотов.
JavaScript может читать DOM и отображать довольно точное представление об этом с помощью canvas
. Я работал над сценарием, который преобразует HTML в изображение холста. Решил сегодня внедрить его в отправку отзывов, как вы описали.
Сценарий позволяет создавать формы обратной связи, которые включают в себя скриншот, созданный в браузере клиента, вместе с формой. Снимок экрана основан на DOM и, как таковой, может не быть на 100% точным к реальному представлению, поскольку он не создает фактического снимка экрана, а создает снимок экрана на основе информации, доступной на странице.
Не требует рендеринга с сервера, так как все изображение создается в браузере клиента. Сам скрипт HTML2Canvas все еще находится в очень экспериментальном состоянии, так как он не анализирует почти столько атрибутов CSS3, сколько я хотел бы, ни поддерживает загрузку изображений CORS, даже если прокси-сервер был доступен.
Все еще довольно ограниченная совместимость браузера (не потому, что больше не может быть поддержано, просто не было времени сделать его более кросс-браузерным).
Для получения дополнительной информации посмотрите примеры здесь:
http://hertzen.com/experiments/jsfeedback/
edit Сценарий html2canvas теперь доступен отдельно здесь и некоторые примеры здесь.
edit 2 Еще одно подтверждение того, что Google использует очень похожий метод (на самом деле, основываясь на документации, единственным существенным отличием является их асинхронный метод обхода/рисования), можно найти в этой презентации Эллиотта Спрена из команды Google Feedback: http://www.elliottsprehn.com/preso/fluentconf/
Теперь ваше веб-приложение может использовать "собственный" снимок экрана для всего рабочего стола клиента, используя getUserMedia()
:
Взгляните на этот пример:
https://www.webrtc-experiment.com/Pluginfree-Screen-Sharing/
Клиент должен будет использовать хром (на данный момент) и должен будет включить поддержку захвата экрана под флагами chrome://.
Как упоминает Никлас, вы можете использовать библиотеку html2canvas, чтобы сделать скриншот с помощью браузера js. Я разработаю его ответ в этом пункте, предоставив пример создания скриншота с использованием этой библиотеки (в этом фрейме вопроса):
function report() {
let region = document.querySelector("body"); // whole screen
html2canvas(region, {
onrendered: function(canvas) {
let pngUrl = canvas.toDataURL(); // png in dataURL format
let img = document.querySelector(".screen");
img.src = pngUrl;
// here you can allow user to set bug-region
// and send it with 'pngUrl' to server
},
});
}
.container {
margin-top: 10px;
border: solid 1px black;
}
<script src="/html2canvas.min.js"></script>
<div>Screenshot tester</div>
<button onclick="report()">Take screenshot</button>
<div class="container">
<img width="75%" class="screen">
</div>
В функции report()
onrendered
после получения изображения в качестве data-uri, вы можете показать его пользователю и позволить ему нарисовать "область ошибки" мышью, а затем отправить скриншот и координаты области на сервер.
В этом примере была сделана async/await
версия: с хорошей makeScreenshot()
.
Простой пример, который позволяет вам сделать скриншот, выбрать регион, описать ошибку и отправить запрос POST (здесь jsfiddle) (основная функция - report()
).
async function report() {
let screenshot = await makeScreenshot(); // png dataUrl
let img = q(".screen");
img.src = screenshot;
let c = q(".bug-container");
c.classList.remove('hide')
let box = await getBox();
c.classList.add('hide');
send(screenshot,box); // sed post request with bug image, region and description
alert('To see POST requset with image go to: chrome console > network tab');
}
// ----- Helper functions
let q = s => document.querySelector(s); // query selector helper
window.report = report; // bind report be visible in fiddle html
async function makeScreenshot(selector="body")
{
return new Promise((resolve, reject) => {
let node = document.querySelector(selector);
html2canvas(node, { onrendered: (canvas) => {
let pngUrl = canvas.toDataURL();
resolve(pngUrl);
}});
});
}
async function getBox(box) {
return new Promise((resolve, reject) => {
let b = q(".bug");
let r = q(".region");
let scr = q(".screen");
let send = q(".send");
let start=0;
let sx,sy,ex,ey=-1;
//console.log({b,r, scr});
b.addEventListener("click", e=>{
if(start==0) {
sx=e.offsetX+scr.offsetLeft;
sy=e.offsetY+b.offsetTop;
ex=0;
ey=0;
r.style.top = sy +'px';
r.style.left =sx +'px';
r.style.width = 0;
r.style.height = 0;
}
start=(start+1)%3;
});
b.addEventListener("mousemove", e=>{
//console.log(e)
if(start==1) {
ex=e.offsetX+scr.offsetLeft-sx;
ey=e.offsetY+b.offsetTop-sy
r.style.width = ex +'px';
r.style.height = ey +'px';
}
});
send.addEventListener("click", e=>{
start=0;
let a=100/75 //zoom out img 75%
resolve({
x:Math.floor((sx-scr.offsetLeft)*a),
y:Math.floor((sy-b.offsetTop)*a),
width:Math.floor(ex*a),
height:Math.floor(ey*a),
desc: q('.bug-desc').value
});
});
});
}
function send(image,box) {
let formData = new FormData();
let req = new XMLHttpRequest();
formData.append("box", JSON.stringify(box));
formData.append("screenshot", image);
req.open("POST", '/upload/screenshot');
req.send(formData);
}
.bug-container { background: rgb(255,0,0,0.1); margin-top:20px; text-align: center; }
.send { border-radius:5px; padding:10px; background: green; cursor: pointer; }
.region { position: absolute; background: rgba(255,0,0,0.4); }
.example { height: 100px; background: yellow; }
.bug { margin-top: 10px; cursor: crosshair; }
.hide { display: none; }
<script src="/html2canvas.min.js"></script>
<body>
<div>Screenshot tester</div>
<button onclick="report()">Report bug</button>
<div class="example">Lorem ipsum</div>
<div class="bug-container hide">
<div>Select bug region</div>
<div class="bug">
<img width="75%" class="screen" >
<div class="region"></div>
</div>
<div>
<textarea class="bug-desc">Describe bug here...</textarea>
</div>
<div class="send">SEND BUG</div>
</div>
</body>