JSFiddle - React, Tailwind, and code Playground

by Black Diamond

HTML

<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>

CSS

.bug-container {
 background: rgb(255,0,0,0.1);  
 margin-top:20px;
 text-align: center;
}

.bug {
    margin-top: 10px; 
    cursor: crosshair;
   /*  border: solid 1px black;       */   
}

.hide {
  display: none;
}

.example {
  height: 100px;
  background: yellow;
}

.region {
  position: absolute;
   
  background: rgba(255,0,0,0.4);
}

.send {
  border-radius:5px;
  padding:10px;
  background: green;
  cursor: pointer;
  
}

JavaScript

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),
         ...