Jump to content

Erasing Rectangles Over An Image in HTML/JS/CSS

I am trying to make a program where the user uploads a map and can cover it and uncover it. I can manage to write a code to allow the user to cover the map, but not to uncover the map. I am trying to use CSS sprites that take a piece of the uploaded image and makes that what the user paints. Since the image is uploads, it does not have a url, so using CSS sprites does not work. Is there a way to use CSS sprites, or an easier way? Note: The image is in an HTML canvas.

 

Here is the program, if showing it helps:

<!DOCTYPE html>
<html> 
  <head>
    <title>Dungeon Crawler</title>
    <style>
    #title {
  font-variant: small-caps;
  font-size: 50px;
}
    </style>  
  </head>
  <body>   
    
    <h1 id = "title">Dungeon Crawler</h1>

   
<b id = importMapText> Import Map: </b><span id = "imageLoader"><input type="file" accept="image/*" name="imageLoader"/></span>
<input type="button" id = "back" value="Back" onclick="back()" />
    <p>
   
 <span id = "tools"> <select id="coverOrUncover">
  <option value="uncover"> Uncover</option> 
  <option value="cover"> Cover </option>   
</select> 
      
the map with a brush size of 
<input type="text" value = "50" name = "size" id = "size"> pixels. 
</span>

      
    <canvas id="imageCanvas"></canvas>
    
    <script src="https://cdn.jsdelivr.net/processing.js/1.4.8/processing.min.js"></script> 
    
    <script>
      var vv = document.getElementById("tools");
        vv.style.display = "none";
      var v = document.getElementById("title");
        v.style.display = "block";
      var w = document.getElementById("imageCanvas");
        w.style.display = "none";
      var x = document.getElementById("back");
    x.style.display = "none";
    
   var imageLoader = document.getElementById('imageLoader');
    imageLoader.addEventListener('change', handleImage, false);
var canvas = document.getElementById('imageCanvas');
var ctx = canvas.getContext('2d');

      document.getElementById("imageLoader").innerHTML = "<input type=\"file\" name=\"imageLoader\">"

    
      
function handleImage(e){
  var vv = document.getElementById("tools");
        vv.style.display = "block";
  var v = document.getElementById("title");
        v.style.display = "none";
  var w = document.getElementById("imageCanvas");
        w.style.display = "block";
  
  document.getElementById("imageLoader").innerHTML = ""
  document.getElementById("size").value = "50"
    var y = document.getElementById("importMapText");
    y.style.display = "none";
  
    var z = document.getElementById("back");
    z.style.display = "block";
  
  // ^ shows stuff that need to and hides things that don't
  
  var reader = new FileReader();
    reader.onload = function(event){
        var img = new Image();
        img.onload = function(){
            canvas.width = img.width;
            canvas.height = img.height;
            ctx.drawImage(img,0,0);
        }
        img.src = event.target.result;
    }
    reader.readAsDataURL(e.target.files[0]);  
  // ^ Prints the image to the canvas
}

      
      function back(){
        var vv = document.getElementById("tools");
        vv.style.display = "none";
        var v = document.getElementById("title");
        v.style.display = "block";
        
        var w = document.getElementById("imageCanvas");
        w.style.display = "none";

        document.getElementById("imageLoader").innerHTML = "<input type=\"file\" accept=\"image/*\" name=\"imageLoader\">"
        
        var y = document.getElementById("importMapText");
        y.style.display = "block";
  
        var z = document.getElementById("back");
        z.style.display = "none";
  
        // ^ shows stuff that need to and hides things that don't
      }
      
      </script>
    
    <script> 
    var sketchProc = function(processingInstance) {
     with (processingInstance) {
        size(700, 400); 
        frameRate(30);
        
        // ProgramCodeGoesHere
 var size = document.getElementById("size").value; 
    size = parseInt(size, 10);
    var coverOrUncover = document.getElementById("coverOrUncover").value;     
     
     draw = function() {
       size = document.getElementById("size").value; 
       size = parseInt(size, 10);
       
       fill(0, 0, 0);
       noStroke();
       rect(mouseX, mouseY, size, size);  
};

            }};

    // Get the canvas that Processing-js will use
    var canvas = document.getElementById("imageCanvas"); 
    // Pass the function sketchProc (defined in myCode.js) to Processing's constructor.
    var processingInstance = new Processing(canvas, sketchProc);   
    </script>
    
  </body>

</html>

 

Link to comment
Share on other sites

Link to post
Share on other sites

Maybe I can place a canvas on top of another, one with the image and the other with the user drawing and erasing, but I don't know how.

Link to comment
Share on other sites

Link to post
Share on other sites

When you are drawing the rects you are overwriting the pixel data for the image behind! So you cannot simply "erase" the rectangles. What you need to do when "erasing" the rects is redraw over the rect with pixel data of the original image for where the rect covers it

 

See third demo of image() here drawing subsection of an image

https://p5js.org/reference/#/p5/image

 

Also you can "stack" multiple canvas's to create "layers" you have to use CSS absolute position/z-layer so they overlap.

https://html5.litten.com/using-multiple-html5-canvases-as-layers/

Link to comment
Share on other sites

Link to post
Share on other sites

On 11/9/2019 at 5:08 AM, C2dan88 said:

Also you can "stack" multiple canvas's to create "layers" you have to use CSS absolute position/z-layer so they overlap.

https://html5.litten.com/using-multiple-html5-canvases-as-layers/

So I worked with two canvases the way you suggested, thank you, and wrote a function to erase the rectangles on the second canvas. But I ran into a new problem that is probably a simple fix; the program does erase and draw properly, but the full image is no longer displayed, only a small piece of the uploaded image is displayed.

 

Here is the code, in case the problem is just some kind of syntax error I didn't notice:

<!DOCTYPE html>
<html> 
  <head>
    <title>Dungeon Crawler</title>
    <style>
    #title {
  font-variant: small-caps;
  font-size: 50px;
}
    </style>  
  </head>
  <body>   
    
    <h1 id = "title">Dungeon Crawler</h1>

   
<b id = importMapText> Import Map: </b><span id = "imageLoader"><input type="file" accept="image/*" name="imageLoader"/></span>
<input type="button" id = "back" value="Back" onclick="back()" />
    <p>
   
 <span id = "tools"> <select id="coverOrUncover">
  <option value="uncover"> Uncover</option> 
  <option value="cover"> Cover </option>   
</select> 
      
the map with a brush size of 
<input type="text" value = "50" name = "size" id = "size"> pixels. 
</span>

      
      <div style="position: relative;">
 <canvas id="imageCanvas" width="100" height="100" 
   style="position: absolute; left: 0; top: 50; z-index: 0;"></canvas>
 <canvas id="drawingCanvas" width="100" height="100" 
   style="position: absolute; left: 0; top: 50; z-index: 1;"></canvas>
</div>
      
    
    
    <script src="https://cdn.jsdelivr.net/processing.js/1.4.8/processing.min.js"></script> 
    
    <script>
      var ii = document.getElementById("drawingCanvas");
      ii.style.display = "none";
      var vv = document.getElementById("tools");
        vv.style.display = "none";
      var v = document.getElementById("title");
        v.style.display = "block";
      var w = document.getElementById("imageCanvas");
        w.style.display = "none";
      var x = document.getElementById("back");
    x.style.display = "none";
    
   var imageLoader = document.getElementById('imageLoader');
    imageLoader.addEventListener('change', handleImage, false);
var canvas = document.getElementById('imageCanvas');
var ctx = canvas.getContext('2d');

      document.getElementById("imageLoader").innerHTML = "<input type=\"file\" name=\"imageLoader\">"

    
      
function handleImage(e){
  var ii = document.getElementById("drawingCanvas");
      ii.style.display = "block";
  var vv = document.getElementById("tools");
        vv.style.display = "block";
  var v = document.getElementById("title");
        v.style.display = "none";
  var w = document.getElementById("imageCanvas");
        w.style.display = "block";
  
  document.getElementById("imageLoader").innerHTML = ""
  document.getElementById("size").value = "50"
    var y = document.getElementById("importMapText");
    y.style.display = "none";
  
    var z = document.getElementById("back");
    z.style.display = "block";
  
  // ^ shows stuff that need to and hides things that don't
  
  var reader = new FileReader();
    reader.onload = function(event){
        var img = new Image();
        img.onload = function(){
            canvas.width = img.width;
            canvas.height = img.height;
            ctx.drawImage(img,0,0);
        }
        img.src = event.target.result;
    }
    reader.readAsDataURL(e.target.files[0]);  
  // ^ Prints the image to the canvas
}

      
      function back(){
        var ii = document.getElementById("drawingCanvas");
      ii.style.display = "none";
        var vv = document.getElementById("tools");
        vv.style.display = "none";
        var v = document.getElementById("title");
        v.style.display = "block";
        
        var w = document.getElementById("imageCanvas");
        w.style.display = "none";

        document.getElementById("imageLoader").innerHTML = "<input type=\"file\" accept=\"image/*\" name=\"imageLoader\">"
        
        var y = document.getElementById("importMapText");
        y.style.display = "block";
  
        var z = document.getElementById("back");
        z.style.display = "none";
  
        // ^ shows stuff that need to and hides things that don't
      }
      
      </script>
    
    <script> 
      var canvas = document.getElementById('imageCanvas');
      var width1 = canvas.width;
      var height1 = canvas.height;
      
      drawingCanvas.width  = width1; // in pixels
      drawingCanvas.height = height1; // in pixels
    var sketchProc = function(processingInstance) {
     with (processingInstance) {
        size(700, 400); 
        frameRate(30);
        
        // Draws on Map
       //  ___________________________________________
       
    var isMouseDown = false;
    var size = document.getElementById("size").value; 
    size = parseInt(size, 10);
     
     draw = function() {
       size = document.getElementById("size").value; 
       size = parseInt(size, 10);
       var coverOrUncover = document.getElementById("coverOrUncover").value;     
       var c  = document.getElementById("drawingCanvas");
       var ctx = c.getContext("2d");
       
       
       drawingCanvas.onmousedown = function(){
         isMouseDown = true
       };
       
       drawingCanvas.onmouseup = function(){
         isMouseDown = false
       };
         
        
       document.onmousedown = function() { 
         if(isMouseDown) { 
          if(coverOrUncover === "cover"){
             fill(0, 0, 0);
             noStroke();
             rect(mouseX - (size/2), mouseY - (size/2), size, size); 
         } else if(coverOrUncover === "uncover"){
           ctx.clearRect(mouseX - (size/2), mouseY - (size/2), size, size);
         }
       }
     }
       
       document.onmousemove = function() { 
         if(isMouseDown) { 
           if(coverOrUncover === "cover"){
             fill(0, 0, 0);
             noStroke();
             rect(mouseX - (size/2), mouseY - (size/2), size, size); 
         } else if(coverOrUncover === "uncover"){
           ctx.clearRect(mouseX - (size/2), mouseY - (size/2), size, size);
         }
            
         }
       }; 
        
};

            }};

    // Get the canvas that Processing-js will use
    var canvas = document.getElementById("drawingCanvas"); 
    // Pass the function sketchProc (defined in myCode.js) to Processing's constructor.
    var processingInstance = new Processing(canvas, sketchProc);   
    </script>
    
  </body>

</html>

 

Link to comment
Share on other sites

Link to post
Share on other sites

  • 1 month later...
  • 4 weeks later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×