Search code examples
canvaseraseresponsive

How to erase canvas using the cursor


I'd like to add a responsive canvas to a web page. This is just a black div and should be erasable with the cursor.

Div 1 (canvas) on top of div 2 (text). The cursor should erase div 1 and reveal div 2.

Update

I'm using this code but it's not working.

var canvas = document.getElementById("canvasTop");
var ctx = canvas.getContext("2d");
    ctx.lineWidth = 10;
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    ctx.fillStyle = "skyblue";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

var canvasOffset = $("#canvasTop").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;

var startX;
var startY;
var isDown = false;

function handleMouseDown(e) {
    e.preventDefault();
    startX = parseInt(e.clientX - offsetX);
    startY = parseInt(e.clientY - offsetY);
    isDown = true;
}

function handleMouseUp(e) {
    e.preventDefault();
    isDown = false;
}

function handleMouseOut(e) {
    e.preventDefault();
    isDown = false;
}

function handleMouseMove(e) {
    if (!isDown) {
        return;
    }
    mouseX = parseInt(e.clientX - offsetX);
    mouseY = parseInt(e.clientY - offsetY);

    // Put your mousemove stuff here
    ctx.save();
    ctx.globalCompositeOperation = "destination-out";
    ctx.beginPath();
    ctx.moveTo(startX, startY);
    ctx.lineTo(mouseX, mouseY);
    ctx.stroke();
    startX = mouseX;
    startY = mouseY;
}

$("#canvasTop").mousedown(function (e) {
    handleMouseDown(e);
});
$("#canvasTop").mousemove(function (e) {
    handleMouseMove(e);
});
$("#canvasTop").mouseup(function (e) {
    handleMouseUp(e);
});
$("#canvasTop").mouseout(function (e) {
    handleMouseOut(e);
});
html, body {height:100%}
body {
  margin:0; padding:0;
}
#wrapper {
  position:relative; 
  margin:auto; 
  width:100%; 
  height:100%; 
  background-color:#ffffff
}
#canvasTop {
  position:absolute; 
  top:0px; 
  left:0px; 
  width:100%; 
  height:100%;
}
#text {
  position:absolute; 
  left:0; 
  right:0; 
  margin-left:auto; 
  margin-right:auto; 
  width:400px; 
  height:200px; 
  text-align:center; 
  top: 50%; 
  transform:translateY(-50%); 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
    <canvas id="canvasTop" width=100% height=100%></canvas>
    <div id="text">
    <p> Text Text Text Text Text Text Text Text Text</p>
    <p> Text Text Text Text Text Text</p>
    <p> Text Text Text Text Text Text</p>
    <p> Text Text Text Text Text Text Text Text Text</p>
   </div>
</div>

Hope anyone can help!

Thanks


Solution

  • These changes to your code should create your "scratch-off" effect:

    • Move #text before #canvasTop
    • Don't use CSS to change the canvas size. Doing so will distort the canvas.
    • Set the canvas element's width & height to equal #wrapper's width & height.

    Here is refactored code with the changes annotated:

    var canvas = document.getElementById("canvasTop");
    // set the canvas element's width/height to cover #wrapper
    var wrapper=document.getElementById('wrapper');
    var wrapperStyle=window.getComputedStyle(wrapper,null);
    canvas.width=parseInt(wrapperStyle.getPropertyValue("width"));
    canvas.height=parseInt(wrapperStyle.getPropertyValue("height"));
    //
    var ctx = canvas.getContext("2d");
        ctx.lineWidth = 10;
        ctx.lineCap = "round";
        ctx.lineJoin = "round";
        ctx.fillStyle = "skyblue";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        // set "erase" compositing once at start of app for better performance
        ctx.globalCompositeOperation = "destination-out";
    
    var canvasOffset = $("#canvasTop").offset();
    var offsetX = canvasOffset.left;
    var offsetY = canvasOffset.top;
    
    var startX;
    var startY;
    var isDown = false;
    
    function handleMouseDown(e) {
        e.preventDefault();
        startX = parseInt(e.clientX - offsetX);
        startY = parseInt(e.clientY - offsetY);
        isDown = true;
    }
    
    function handleMouseUp(e) {
        e.preventDefault();
        isDown = false;
    }
    
    function handleMouseOut(e) {
        e.preventDefault();
        isDown = false;
    }
    
    function handleMouseMove(e) {
        if (!isDown) {
            return;
        }
        mouseX = parseInt(e.clientX - offsetX);
        mouseY = parseInt(e.clientY - offsetY);
    
        // Put your mousemove stuff here
        ctx.beginPath();
        ctx.moveTo(startX, startY);
        ctx.lineTo(mouseX, mouseY);
        ctx.stroke();
        startX = mouseX;
        startY = mouseY;
    }
    
    $("#canvasTop").mousedown(function (e) {
        handleMouseDown(e);
    });
    $("#canvasTop").mousemove(function (e) {
        handleMouseMove(e);
    });
    $("#canvasTop").mouseup(function (e) {
        handleMouseUp(e);
    });
    $("#canvasTop").mouseout(function (e) {
        handleMouseOut(e);
    });
    html, body {height:100%}
    body { margin:0; padding:0; }
    #wrapper {
      position:relative; 
      margin:auto; 
      width:100%; 
      height:100%; 
      background-color:#ffffff;
    }
    #canvasTop {
      position:absolute; 
      top:0px; 
      left:0px; 
    }
    #text {
      position:absolute; 
      left:0; 
      right:0; 
      margin-left:auto; 
      margin-right:auto; 
      width:400px; 
      height:200px; 
      text-align:center; 
      top: 50%; 
      transform:translateY(-50%); 
    }
    #canvas{border:1px solid red; }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <h4>Drag the mouse over center to "scratch-off" reveal</h4>
    <div id="wrapper">
      <!-- move #text before #canvasTop -->
      <div id="text">
        <p> Text Text Text Text Text Text Text Text Text</p>
        <p> Text Text Text Text Text Text</p>
        <p> Text Text Text Text Text Text</p>
        <p> Text Text Text Text Text Text Text Text Text</p>
      </div>
      <canvas id="canvasTop" width=512 height=512></canvas>
    </div>