0

I'm using heatmap.js in Google Apps Script and I am trying to resize the heatmap canvas (where I can actually plot points) to fit an image. How can I change the javascript or styling to make this work?

CODE: https://jsfiddle.net/nateomardavis/51h2guL9/

  • The wrapper has a black border.
  • The heatmap div has a blue border.
  • The canvas has a red border.

How it Should Work: I should be able to mark the heatmap anywhere on the image. The wrapper, heatmap div and canvas should all be sized based on the size of the image.

How it Currently Works: I can only mark the heatmap inside the blue/black border. My javascript resizes the canvas to fit the image, but not the bounds of the heatmap.

What I've Tried: You can see in the fiddle how I've tried to change what the javascript is resizing (lines 88-90).I also thought about using the using the image as the background-image of the heatmap div but the sizing wasn't right and I wanted to be able to save the heatmap and image as one layer (for printing/saving). I also tried changing the size of the image (line 101) but anything above 55% would cut the image off.

The screenshot below is just for reference, but the full working code is in the fiddle. I have it all under HTML because that's how it works in Google Apps Script.

enter image description here

 <!DOCTYPE html>
    <html>
  <head>
    <base target="_top">
    <script type="text/javascript" src="https://www.patrick-wied.at/static/heatmapjs/assets/js/heatmap.min.js"></script>
   <style>

   html, body {
     width:  100%;
     height: 100%;
  }

  html { 
    color: #333;
    font-family: sans-serif;
    font-size: 16pt;
    font-weight: 100;
    line-height: 1.5em;
  }

  .wrapper { 
    width: 100%; 
    height:100%; 
    background:rgba(0,0,0,.03); 
    border:3px solid black; 
  }

  .heatmap { 
    width:100%; 
    height:100%;
    background-position: top;
    background-repeat: no-repeat;
    background-size: contain;
    position: relative;
    border:3px solid blue; 
 }

 .canvas {
   border:3px solid red; 
 }

  </style>

  </head>

 <body>
   <button class="clear">Clear</button>
   <button onclick="printPage()" class="print-btn no-print" style="">Print</button>
   <p id="coords"></p>
    <div id="wrapper" class="wrapper"> <!-- black box on web app-->
      <div id="heatmap" class = "heatmap" style="position: relative;"> <!-- blue box on web app-->
      <canvas id="canvas" class="canvas"></canvas> <!-- red box on web app-->
    </div> 
  </div>


<script>



//CREATE HEATMAP
  window.onload = function() {
    var heatmapInstance = h337.create({
      container: document.querySelector('.heatmap'),
      gradient: {
        '.25': 'black',
        '.5': 'red',
        '.75': 'white'
      },
      radius: 20
    });

    document.querySelector('.wrapper').onclick = function(ev) {
      heatmapInstance.addData({
        x: ev.layerX,
        y: ev.layerY,
        value: 1
      });
    };

     document.querySelector('.clear').onclick = function() {
       //heatmapInstance._renderer._clear();
       heatmapInstance.setData({data:[]}); 
      };

//RESIVE CANVAS TO FIT IMAGE
  //http://jsfiddle.net/6ZsCz/1135/
  var canvas = document.getElementById('canvas');  //v1
  //var canvas = document.getElementById('heatmap'); //v2
  //var canvas = document.getElementById('wrapper');  //v3
    var ctx = canvas.getContext('2d');
      ctx.canvas.width  = window.innerWidth;
      ctx.canvas.height = window.innerHeight; 
    var imageObj = new Image();


  imageObj.onload = function() {
    canvas.width = imageObj.width; // version 2
    canvas.height = imageObj.height;  // version 2  
    ctx.drawImage(imageObj,0,0); // version 2
    //ctx.drawImage(imageObj, 0, 0, imageObj.width * 0.5, imageObj.height * 0.5); //version 1

  };
  imageObj.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Soccer_Field_Transparant.svg/1200px-Soccer_Field_Transparant.svg.png';

 };


//MOUSE COORDINATES
//works inside heatmap
  function getCursorPosition(canvas, event) {
    const rect = canvas.getBoundingClientRect()
    const x = event.clientX - rect.left
    const y = event.clientY - rect.top
    var coor = "X coords: " + x + ", Y coords: " + y;
    document.getElementById("coords").innerHTML = coor;
  }

  const canvas = document.querySelector('.heatmap')
  canvas.addEventListener('mousedown', function(e) {
    getCursorPosition(canvas, e)
  })


  function printPage() {
    window.print();
  }

     </script>

  </body>

</html>
N.O.Davis
  • 501
  • 2
  • 10
  • 22

1 Answers1

0

After lots of tinkering, I was able to figure it out: https://jsfiddle.net/nateomardavis/p1kwrhmv

  1. I used img and gave it a background-image with CSS.
  2. I then set the heatmap layer to relative and the image layer to absolute using the solution HERE.
  3. Last, I then set the image layer css using the method outlined HERE.

    .heatmap {
      background-size: contain;
      background-repeat: no-repeat;
      width: 100%;
      height: 300%; /*if the image is bigger than screen, this is needed */
      position: relative;
    }
    
    .backgroundIMG {
      background-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Soccer_Field_Transparant.svg/1200px-Soccer_Field_Transparant.svg.png');
      background-size: contain;
      background-repeat: no-repeat;
      position: absolute;
      width: 100%;
      height: 0;
      padding-top: 151.33%;
    }
    
N.O.Davis
  • 501
  • 2
  • 10
  • 22