title: PDF.JS with CANVAS Draw : Draw rectangle in canvas with PDF loaded using pdf.js
body: <p>I need to </p>
  
  <p>1) First  select PDF </p>
  
  <p>2) Load it using PDF.js (select page) and</p>
  
  <p>3) Draw rectangle on it using canvas. </p>
  
  <p>For that I was able to make, most of my requirements but when i draw rectangle on canvas PDF, then design gets disturb and creates multiple rectangle instead of single. </p>
  
  <p>I just need one rectangle. For example this rectangle design is disturbing creates multiple. Is it possible to create only 1 rectangle ? </p>
  
  <p>Issue Ref. <a href="http://prntscr.com/n4h1np" rel="nofollow noreferrer">http://prntscr.com/n4h1np</a></p>
  
  <p><strong>Sample Demo</strong> : <a href="https://testchat32.tk/v/PDF/03.html" rel="nofollow noreferrer">https://testchat32.tk/v/PDF/03.html</a></p>
  
  <p>Any help or suggestion on this are most welcome. </p>
  
  <p>Thanks in advance.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>                 /*load pdf*/
              var __PDF_DOC,
                  __CURRENT_PAGE,
                  __TOTAL_PAGES,
                  __PAGE_RENDERING_IN_PROGRESS = 0,
                  __CANVAS = $('#pdf-canvas').get(0),
                  __CANVAS_CTX = __CANVAS.getContext('2d');
              
              function showPDF(pdf_url) {
                  $("#pdf-loader").show();
                  PDFJS.getDocument({ url: pdf_url }).then(function(pdf_doc) {
                      
                      __PDF_DOC = pdf_doc;
                      __TOTAL_PAGES = __PDF_DOC.numPages;
                      
                      // Hide the pdf loader and show pdf container in HTML
                      $("#pdf-loader").hide();
                      $("#pdf-contents").show();
                      $("#pdf-total-pages").text(__TOTAL_PAGES);
              
                      // Show the first page
                      showPage(1);
                  }).catch(function(error) {
                      // If error re-show the upload button
                      $("#pdf-loader").hide();
                      $("#upload-button").show();
                      
                      //alert(error.message);
                  });;
              }
              
              function showPage(page_no) {
                  __PAGE_RENDERING_IN_PROGRESS = 1;
                  __CURRENT_PAGE = page_no;
              
                  // Disable Prev &amp; Next buttons while page is being loaded
                  $("#pdf-next, #pdf-prev").attr('disabled', 'disabled');
              
                  // While page is being rendered hide the canvas and show 
                  $("#pdf-canvas").hide();
                  $("#page-loader").show();
              
                  // Update current page in HTML
                  $("#pdf-current-page").text(page_no);
                  
                  jQuery("#pdf_page_no").val(page_no);
                  jQuery(".pdf_page_no").val(page_no);
                  
                  // Fetch the page
                  __PDF_DOC.getPage(page_no).then(function(page) {
                      // As the canvas is of a fixed width we need to set the scale of the viewport accordingly
                      var scale_required = __CANVAS.width / page.getViewport(1).width;
              
                      // Get viewport of the page at required scale
                      var viewport = page.getViewport(scale_required);
              
                      // Set canvas height
                      __CANVAS.height = viewport.height;
              
                      var renderContext = {
                          canvasContext: __CANVAS_CTX,
                          viewport: viewport
                      };
                      
                      // Render the page contents in the canvas
                      page.render(renderContext).then(function() {
                          __PAGE_RENDERING_IN_PROGRESS = 0;
              
                          // Re-enable Prev &amp; Next buttons
                          $("#pdf-next, #pdf-prev").removeAttr('disabled');
              
                          // Show the canvas and hide the page loader
                          $("#pdf-canvas").show();
                          $("#page-loader").hide();
                      });
                  });
              }
              
              // Upon click this should should trigger click on the #file-to-upload 
              // This is better than showing the not-good-looking file input element
              $("#upload-button").on('click', function() {
                  $("#file-to-upload").trigger('click');
              });
              
              // When user chooses a PDF file
              $("#file-input").on('change', function() {
                  // Validate whether PDF
                  if(['application/pdf'].indexOf($("#file-input").get(0).files[0].type) == -1) {
                      alert('Error : Not a PDF');
                      return; // Viral vvvvvvvv
                  }
              
                  
                  // Send the object url of the pdf
                  showPDF(URL.createObjectURL($("#file-input").get(0).files[0]));
                  jQuery('#pdf-contents').removeClass('test');
                  $('#pdf-signatur-popup').modal('show');
              });
              
              // Previous page of the PDF
              $("#pdf-prev").on('click', function() {
                  if(__CURRENT_PAGE != 1)
                      showPage(--__CURRENT_PAGE);
              });
              
              // Next page of the PDF
              $("#pdf-next").on('click', function() {
                  if(__CURRENT_PAGE != __TOTAL_PAGES)
                      showPage(++__CURRENT_PAGE);
              });
              /*load pdf*/
              
              
              
              
              /* Draw On PDF ST */
              "use strict";
              requestAnimationFrame(mainLoop);
              const canvas = document.getElementById("pdf-canvas");
              const ctx = canvas.getContext("2d");
              const storedRects = [];
              const baseImage = loadImage("");
              var refresh = true;
              const rect = (() =&gt; {
                  var x1, y1, x2, y2;
                  var show = false;
                  function fix() {
                      rect.x = Math.min(x1, x2);
                      rect.y = Math.min(y1, y2);
                      rect.w = Math.max(x1, x2) - Math.min(x1, x2);
                      rect.h = Math.max(y1, y2) - Math.min(y1, y2);
                      
              
                       jQuery("body").click(function(e) {
                          console.log(rect.x+'='+rect.y+'='+rect.w+'='+rect.h);
                           $('#output').html('current x : '+rect.x+', current y : '+rect.y+', width : '+rect.w+', height : '+rect.h);
                           
                          if (e.target.id == "pdf-canvas") {
                              ddrag();
                              jQuery(".position_x").val(rect.x);
                              jQuery(".position_y").val(rect.y);
                              jQuery(".position_w").val(rect.w);
                              jQuery(".position_h").val(rect.h);
                          }
                       });
                  }
              
                  function draw(ctx) { ctx.strokeRect(this.x, this.y, this.w, this.h) }
                  const rect = {x : 0, y : 0, w : 0, h : 0,  draw};
                  const API = {
                      restart(point) {
                          x2 = x1 = point.x;
                          y2 = y1 = point.y;
                          fix();
                          show = true;
                      },
                      update(point) {
                          x2 = point.x;
                          y2 = point.y;
                          fix();
                          show = true;
                      },
                      toRect() {
                          show = false;
                          return Object.assign({}, rect);
                      },
                      draw(ctx) {
                          if (show) { rect.draw(ctx) }
                      },
                      show : false,
                  }
                  return API;
              })();
              
              function loadImage(url) {
                  const image = new Image();
                  image.src = url;
                  image.onload = () =&gt; refresh = true;
                  return image;
              }
              
              const mouse = {
                  button : false,
                  x : 0,
                  y : 0,
                  down : false,
                  up : false,
                  element : null,
                  event(e) {
                      const m = mouse;
                      m.bounds = m.element.getBoundingClientRect();
                      m.x = e.pageX - m.bounds.left - scrollX;
                      m.y = e.pageY - m.bounds.top - scrollY;
                      const prevButton = m.button;
                      m.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
                      if (!prevButton &amp;&amp; m.button) { m.down = true }
                      if (prevButton &amp;&amp; !m.button) { m.up = true }
                  },
                  start(element) {
                      mouse.element = element;
                      "down,up,move".split(",").forEach(name =&gt; document.addEventListener("mouse" + name, mouse.event));
                  }
              }
              
              mouse.start(canvas);
              function draw() {
                  
                  const storedRects = [];
                  ctx.restore();
                  
                  ctx.drawImage(baseImage, 0, 0, ctx.canvas.width, ctx.canvas.width);
                  ctx.lineWidth = 1;
                  ctx.strokeStyle = "yellow";
                  storedRects.forEach(rect =&gt; rect.draw(ctx));
                  ctx.strokeStyle = "red";
                  rect.draw(ctx);
              }
              function mainLoop() {
                  if (refresh || mouse.down || mouse.up || mouse.button) {
                      refresh = false;
                      if (mouse.down) {
                          mouse.down = false;
                          rect.restart(mouse);
                      } else if (mouse.button) {
                          rect.update(mouse);
                      } else if (mouse.up) {
                          mouse.up = false;
                          rect.update(mouse);
                          //storedRects.push(rect.toRect());
                      }
                      draw();
                  }
                  requestAnimationFrame(mainLoop)
              }
              
              function clearCanvas (canvas)
              {
                  const storedRects = [];
                  //alert(jQuery(".position_x").val());
                  jQuery('#pdf-contents').removeClass('test');
                  
              
                  //alert(URL.createObjectURL($("#file-input").get(0).files[0]))
                  showPDF(URL.createObjectURL($("#file-input").get(0).files[0]));
                  
                  
              } 
              function ddrag(){
                  
                   //const storedRects = [];
                   jQuery('.test #pdf-canvas').mousedown(function(){ 
                   console.log(jQuery(this).parent().parent().attr('class'));
                  if(jQuery(this).parent().parent().attr('class')=="test"){
                      return false;
                  }else{
                      return true;
                  }
                  });
                  jQuery('#pdf-contents').addClass('test');
                  
                      //return false; 
                  
                  
              }
              
                /* Draw On PDF EN */
  
        </code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>                         &lt;!--jquery_ST--&gt;
                      &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;
                      &lt;!--jquery_EN--&gt;
                      &lt;!--bootstrap_ST--&gt;
                      &lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css"&gt;
                      &lt;script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"&gt;&lt;/script&gt;
                      &lt;!--bootstrap_EN--&gt;
                      &lt;!--PDF_JS--&gt;
                      &lt;script src="https://testchat32.tk/v/PDF/pdf.js" &gt;&lt;/script&gt;
                      &lt;script src="https://testchat32.tk/v/PDF/pdf.worker.js" &gt;&lt;/script&gt;
                      &lt;!--PDF_JS--&gt;
                      
                      &lt;div class="card-body b-t"&gt;
                        &lt;form enctype="multipart/form-data" id="frm_tech_msg" name="frm_tech_msg" class="form-horizontal"  action="{{ route('get/pdf') }}" method="post" style="width:100%;"&gt;
                       
                          &lt;input type="hidden" name="media_type" id="media_type" class="media_type" value=""&gt;
                          &lt;input type="hidden" name="position_x" id="position_x" class="position_x" value=""&gt;
                          &lt;input type="hidden" name="position_y" id="position_y" class="position_y" value=""&gt;
                          &lt;input type="hidden" name="position_w" id="position_w" class="position_w" value=""&gt;
                          &lt;input type="hidden" name="position_h" id="position_h" class="position_h" value=""&gt;
                          &lt;input type="hidden" name="pdf_page_no" id="pdf_page_no" class="pdf_page_no" value="1"&gt;
                          &lt;div class="row"&gt;
                            &lt;div class="clip-upload"&gt; 
                              
                              &lt;!--label for="file-input"--&gt; 
                              
                              &lt;a href="javascript:void(0);" class="media-selection" id="media-selection"&gt;&lt;i class="fa fa-paperclip fa-lg" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;
                              &lt;input type="file" class="file-input hide" name="file-input" id="file-input"&gt;
                              &lt;!--   onchange="readURL(this);"--&gt; 
                              
                              &lt;!--/label--&gt;
                              
                              &lt;ul class="media-selection-option" style="padding:50px 0 0 100px;"&gt;
                                &lt;li data-id="1" accept-file=".pdf"&gt;&lt;span&gt;&lt;i class="fa fa-pencil"&gt;&lt;/i&gt;&lt;/span&gt;
                                  &lt;label for="file-input" style="cursor:pointer;"&gt;Select PDF&lt;/label&gt;
                                &lt;/li&gt;
                              &lt;/ul&gt;
                            &lt;/div&gt;
                          &lt;/div&gt;
                        &lt;/form&gt;
                      &lt;/div&gt;
                      
                      &lt;!-- The Modal --&gt;
                      &lt;div class="modal pdf-signatur-popup" id="pdf-signatur-popup"&gt;
                        &lt;div class="modal-dialog"&gt;
                          &lt;div class="modal-content" style="width:630px;"&gt; 
                            
                            &lt;!-- Modal Header --&gt;
                            &lt;div class="modal-header"&gt;
                              &lt;h4 class="modal-title"&gt;Drag to select signature area&lt;/h4&gt;
                              &lt;button type="button" class="close" data-dismiss="modal"&gt;&amp;times;&lt;/button&gt;
                              &lt;div id="output"&gt;&lt;/div&gt;
                            &lt;/div&gt;
                            
                            &lt;!-- Modal body --&gt;
                            &lt;div class="modal-body"&gt;
                              &lt;div id="pdf-main-container" class="pdf-main-container"&gt;
                                &lt;div id="pdf-loader"&gt;Loading document ...&lt;/div&gt;
                                &lt;div id="pdf-contents"&gt;
                                  &lt;div id="pdf-meta"&gt;
                                    &lt;div id="pdf-buttons"&gt;
                                      &lt;button id="pdf-prev"&gt;Previous&lt;/button&gt;
                                      &lt;button onclick="clearCanvas()" class="test1212 btn-reload"&gt;Reload PDF/Reassign area&lt;/button&gt;
                                      &lt;button id="pdf-next"&gt;Next&lt;/button&gt;
                                      &lt;br&gt;
                                    &lt;/div&gt;
                                    &lt;div id="page-count-container"&gt;Page
                                      &lt;div id="pdf-current-page"&gt;&lt;/div&gt;
                                      of
                                      &lt;div id="pdf-total-pages"&gt;&lt;/div&gt;
                                    &lt;/div&gt;
                                  &lt;/div&gt;
                                  &lt;div class="add-remove"&gt;
                                    &lt;canvas id="pdf-canvas" width="595"  style="border:1px solid #000000;cursor:crosshair"&gt;&lt;/canvas&gt;
                                  &lt;/div&gt;
                                &lt;/div&gt;
                              &lt;/div&gt;
                            &lt;/div&gt;
                          &lt;/div&gt;
                        &lt;/div&gt;
                      &lt;/div&gt;
                      &lt;!-- The Modal --&gt;</code></pre>
  </div>
  </div>
  </p>