Googles "Rapporter en feil" eller "Tilbakemeldingsverktøy" lar deg velge et område i nettleservinduet for å lage et skjermbilde som sendes inn sammen med tilbakemeldingen din om en feil.
Skjermbilde av Googles tilbakemeldingsverktøy]1. Skjermbilde av Jason Small, lagt ut i et duplisert spørsmål.
Hvordan gjør de dette? Googles JavaScript-feedback-API lastes fra her og deres oversikt over tilbakemeldingsmodulen vil demonstrere skjermbildefunksjonen.
JavaScript kan lese DOM og gjengi en ganske nøyaktig representasjon av den ved hjelp av canvas
. Jeg har jobbet med et skript som konverterer HTML til et lerretbilde. Bestemte meg i dag for å lage en implementering av det til å sende tilbakemeldinger som du beskrev.
Skriptet lar deg lage tilbakemeldingsskjemaer som inkluderer et skjermbilde, opprettet i klientens nettleser, sammen med skjemaet. Skjermbildet er basert på DOM og kan derfor ikke være 100% nøyaktig i forhold til den virkelige representasjonen, da det ikke lager et faktisk skjermbilde, men bygger skjermbildet basert på informasjonen som er tilgjengelig på siden.
Det krever ingen gjengivelse fra serveren, ettersom hele bildet opprettes i klientens nettleser. Selve HTML2Canvas-skriptet er fortsatt i en veldig eksperimentell tilstand, da det ikke analyserer på langt nær så mye av CSS3-attributtene jeg vil at det skal, og det har heller ikke støtte for å laste inn CORS-bilder selv om en proxy var tilgjengelig.
Fortsatt ganske begrenset nettleserkompatibilitet (ikke fordi flere ikke kunne støttes, bare har ikke hatt tid til å gjøre det mer nettleserstøttet).
For mer informasjon, ta en titt på eksemplene her:
http://hertzen.com/experiments/jsfeedback/
edit html2canvas-skriptet er nå tilgjengelig separat her og noen eksempler her.
rediger 2 En annen bekreftelse på at Google bruker en veldig lik metode (faktisk, basert på dokumentasjonen, er den eneste store forskjellen deres asynkroniseringsmetode for traversing/tegning) finnes i denne presentasjonen av Elliott Sprehn fra Google Feedback-teamet: http://www.elliottsprehn.com/preso/fluentconf/
Webappen din kan nå ta et skjermbilde av hele klientens skrivebord ved hjelp av "getUserMedia()":
Ta en titt på dette eksempelet:
https://www.webrtc-experiment.com/Pluginfree-Screen-Sharing/
Klienten må bruke chrome (foreløpig) og må aktivere støtte for skjermbildeopptak under chrome://flags.
Som Niklas nevnte kan du bruke biblioteket html2canvas til å ta et skjermbilde ved hjelp av JS i nettleseren. Jeg vil utvide svaret hans i dette punktet ved å gi et eksempel på å ta et skjermbilde ved hjelp av dette biblioteket:
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="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<div>Screenshot tester</div>
<button onclick="report()">Take screenshot</button>
<div class="container">
<img width="75%" class="screen">
</div>
I report()
-funksjonen i onrendered
etter å ha fått bilde som data-URI kan du vise det til brukeren og la ham tegne "feilregion" med musen og deretter sende et skjermbilde og regionkoordinater til serveren.
I [dette eksemplet][3] async/await
versjon ble laget: med fin makeScreenshot()
funksjon[.][4].
Enkelt eksempel som lar deg ta skjermbilde, velge region, beskrive feil og sende POST-forespørsel ([her jsfiddle][5]) (hovedfunksjonen er 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;
r.style.width=0;
r.style.height=0;
let drawBox= () => {
r.style.left = (ex > 0 ? sx : sx+ex ) +'px';
r.style.top = (ey > 0 ? sy : sy+ey) +'px';
r.style.width = Math.abs(ex) +'px';
r.style.height = Math.abs(ey) +'px';
}
//console.log({b,r, scr});
b.addEventListener("click", e=>{
if(start==0) {
sx=e.pageX;
sy=e.pageY;
ex=0;
ey=0;
drawBox();
}
start=(start+1)%3;
});
b.addEventListener("mousemove", e=>{
//console.log(e)
if(start==1) {
ex=e.pageX-sx;
ey=e.pageY-sy
drawBox();
}
});
send.addEventListener("click", e=>{
start=0;
let a=100/75 //zoom out img 75%
resolve({
x:Math.floor(((ex > 0 ? sx : sx+ex )-scr.offsetLeft)*a),
y:Math.floor(((ey > 0 ? sy : sy+ey )-b.offsetTop)*a),
width:Math.floor(Math.abs(ex)*a),
height:Math.floor(Math.abs(ex)*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="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/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>