Rudiger Kidd
Rudiger Kidd

Reputation: 496

is mouse in user drawn area on canvas

Basically, a user uploads a picture and then can paint on it, and save the result. Another user can then view the photo and if they click in the same area as painted, something happens. So user 1 can make an area click-able for user 2 by drawing on the photo.

now the upload bit is fine, and painting with help from a tutorial and example I've got sussed out. But defining what area is click-able is a bit harder. For something like a rectangle its easy enough, I made an example.

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');


 var button = new Object();
    button.x = 50;
    button.y = 50;
    button.width = 50;
    button.height = 50;
    button.rgb = "rgb(0, 0, 255)";
    function drawbutton(buttonobject)
    {
        context.fillStyle = buttonobject.rgb;
        context.fillRect (buttonobject.x, buttonobject.y, buttonobject.width, buttonobject.height);
        context.strokeRect(buttonobject.x, buttonobject.y, buttonobject.width, buttonobject.height);
    }
    drawbutton(button);


    function checkIfInsideButtonCoordinates(buttonObj, mouseX, mouseY)
    {
        if(((mouseX > buttonObj.x) && (mouseX < (buttonObj.x + buttonObj.width))) && ((mouseY > buttonObj.y) && (mouseY < (buttonObj.y + buttonObj.height))))
            return true;
        else
            return false;
    }

    $("#myCanvas").click(function(eventObject) {
        mouseX = eventObject.pageX - this.offsetLeft;
        mouseY = eventObject.pageY - this.offsetTop;

        if(checkIfInsideButtonCoordinates(button, mouseX, mouseY))
        {
            button.rgb = "rgb(0, 255, 0)";
            drawbutton(button);
        } else {
            button.rgb = "rgb(255, 0, 0)";
            drawbutton(button);
        }
    });

but when it comes to other shapes like circles, or just someone smothering the page, how would you go about detecting that ?

one thought I had was using the edited layer, making it hidden, and detecting a pixel color of say blue, from here but that limits the color use of the photo and im not entirely sure how to implement it. any other ideas ?

EDIT:

I figured out circles after some tinkering, using Pythagoras theorem to see if mouse coordinates are smaller than the radius, but this assumes circle center of 0,0, so then offset mouse by circles actual center. example

function checkIfInsideButtonCoordinates(buttonObj, mouseX, mouseY) {
actualX = mouseX - buttonObj.x
actualY = mouseY - buttonObj.y
mousesqX = actualX * actualX
mousesqY = actualY * actualY
sqR = buttonObj.r * buttonObj.r
sqC = mousesqX + mousesqY

if (sqC < sqR) return true;
    else return false;
}

Upvotes: 0

Views: 176

Answers (1)

markE
markE

Reputation: 105035

Here’s how to test whether user#2 is inside user#1’s paintings

Create a second canvas used to hit-test whether user#2 is inside of user#1’s paintings.

The hit-test canvas is the same size as the drawing canvas, but it only contains user#1’s paintings…not the image.

When user#1 is painting, also draw their paintings on the hit canvas.

enter image description here

When user#1 is done painting, save all their paintings from the hit canvas.

You have at least 2 ways to save user#1’s paintings from the hit canvas:

  • Serialize all the canvas commands needed to recreate the shapes/paths that user#1 paints.
  • Save the hit canvas as an image using canvas.toDataURL.

When user#2 clicks, check if the corresponding pixel on the hit canvas is filled or is transparent (alpha>0).

    // getImageData for the hit-test canvas (this canvas just contains user#1's paintings)
    imageDataData=hitCtx.getImageData(0,0,hit.width,hit.height).data;

    // look at the pixel under user#2's mouse
    // return true if that pixel is filled (not transparent) 
    function isHit(x,y){
        var pixPos=(x+y*hitWidth)*4+3; 
        return( imageDataData[pixPos]>10)
    }

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/etA5a/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; padding:15px; }
    canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var hit=document.getElementById("hit");
    var hitCtx=hit.getContext("2d");
    var user2=document.getElementById("user2");
    var ctx2=user2.getContext("2d");

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

    var imageDataData;
    var hitWidth=hit.width;

    var img=document.createElement("img");
    img.onload=function(){

        // left canvas: image+user#1 paintings
        ctx.globalAlpha=.25;
        ctx.drawImage(img,0,0);
        ctx.globalAlpha=1.00;
        scribble(ctx,"black");

        // mid canvas: just user#1 paintings (used for hittests)
        scribble(hitCtx,"black");

        // right canvas: user#2
        ctx2.drawImage(img,0,0);

        imageDataData=hitCtx.getImageData(0,0,hit.width,hit.height).data;

    }
    img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/colorhouse.png";


    function scribble(context,color){
        context.beginPath();
        context.moveTo(70,2);
        context.lineTo(139,41);
        context.lineTo(70,41);
        context.closePath();
        context.rect(39,54,22,30);
        context.arc(73,115,3,0,Math.PI*2,false);
        context.fillStyle=color;
        context.fill();
    }


    function handleMouseMove(e){
      var mouseX=parseInt(e.clientX-offsetX);
      var mouseY=parseInt(e.clientY-offsetY);

      // If user#2 has a hit on user#1's painting, mid-canvas turns red
      var color="black";
      if(isHit(mouseX,mouseY)){ color="red"; }
      scribble(hitCtx,color);
    }


    function isHit(x,y){
        var pixPos=(x+y*hitWidth)*4+3; 
        return( imageDataData[pixPos]>10)
    }


    $("#user2").mousemove(function(e){handleMouseMove(e);});


}); // end $(function(){});
</script>

</head>

<body>
    <p>Left: original image with user#1 painting</p>
    <p>Mid: user#1 painting only (used for hit-testing)</p>
    <p>Right: user#2 (move mouse over hit areas)</p>
    <canvas id="canvas" width=140 height=140></canvas>
    <canvas id="hit" width=140 height=140></canvas>
    <canvas id="user2" width=140 height=140></canvas><br>
</body>
</html>

Upvotes: 1

Related Questions