Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
ArjhanToteck

Erasing Rectangles Over An Image in HTML/JS/CSS

Recommended Posts

Posted · Original PosterOP

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 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 post
Share on other sites
Posted · Original PosterOP
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 post
Share on other sites

So when you're loading a new image, you resize the drawing canvas, but fail to resize the image canvas (ctx). Your onload function should look like:

img.onload = function(){
  canvas.width = img.width;
  canvas.height = img.height;
  ctx.canvas.width = img.width;
  ctx.canvas.height = img.height;
  ctx.drawImage(img,0,0);
}
Link to post
Share on other sites

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


×