Search code examples
javascriptcsshtml5-canvaspopup-balloons

how to remove one canvas element from displaying on top of another canvas element


I have 2 canvases. One, the main canvas. Upon which all is drawn, Second, the speech bubble canvas (balloon). Which displays information about specific regions on my main canvas upon client clicks.

I was playing around with my canvas after introducing the speech bubble and came across an issue.

This is a simple code that shows how the speech bubble is introduced:-

http://jsfiddle.net/m1erickson/AJvkN/

My canvas is a timeline, and is scrollable; has historical events plotted on it. Once a user clicks on an event a speech bubble appears.

Now what I don't want to happen is, when a client clicks on the canvas, a speech bubble appears and then scrolls, the speech bubble moves to a new position on the scrolled image, however still showing information about the previous location.

For this we have the hideballoon () which assigns css property left : -200. However this still causes inconsistencies. For example if I drag the canvas from left to right, the balloon doesn't disappear with the scroll, but reappears in a new position.

there is a .remove() function $("#balloon").remove()

http://api.jquery.com/remove/

This successfully removes the balloon however, the issue with this is:- it removes the balloon completely, and no future clicks will pop up any more speech bubbles. This is not what I want. I want something dynamic.

Click on event >> speech bubble appears >> scroll canvas >> speech bubble disappears >> click on canvas >> speech bubble pertaining to new click appears back >> and so on and so forth.


Solution

  • [Edited]

    Use .show() and .hide() to keep the balloon out of your way when its not needed

    When the user scrolls the window then just hide the balloon.

    I assume you're scrolling the window instead of the canvas. If you're scrolling the canvas, just use $("#canvas").scroll( ... ) instead.

    So when you need the balloon:

            // move the balloon canvas to the target
            $("#balloon").css({left:offsetX+X, top:offsetY+Y});
    
            // and show it
            $("#balloon").show();
    

    And hide the balloon when the user clicks on it or when the window scrolls:

        // listen for clicks on the balloon and then hide the balloon
        $("#balloon").click(function(e){ $("#balloon").hide(); });
    
        // listen for scrolls and then hide the balloon
        $(window).scroll(function(e){
            $("#balloon").hide(); 
        });
    

    Here’s working sample code and a Fiddle: http://jsfiddle.net/m1erickson/uWHkv/

    <!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{ width:2000px; background-color: ivory; padding:10px;padding-top:100px; }
        #canvas{border:1px solid red;}
        #balloon{ position:absolute; left:-200px; }
    </style>
    
    <script>
    $(function(){
    
        // get reference to our drawing canvas
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
        // get reference to our balloon canvas
        var balloon=document.getElementById("balloon");
        var popCtx=balloon.getContext("2d");
    
        // get the position of canvas relative to window
        var canvasOffset=$("#canvas").offset();
        var offsetX=canvasOffset.left;
        var offsetY=canvasOffset.top;
    
        // define some targets and their basic info
        var count=1;
        var circles=[];
        for(var x=50;x<1900;x+=50){
            circles.push({
                x:x,  y:120, radius:20,
                color:"blue",  
                info:"I'm #"+(count++)});
        }
    
        // draw the target circles on the canvas
        ctx.fillStyle="yellow";
        ctx.font="16px verdana";
        for(var i=0;i<circles.length;i++){
            drawCircle(circles[i]);
            ctx.beginPath();
            ctx.fillText(i+1,circles[i].x-8,circles[i].y+5);
        }
    
        // listen for clicks on the canvas and show the balloon
        $("#canvas").click(function(e){ 
    
            // get the mouseclick position
            mouseX=parseInt(e.clientX-offsetX);
            mouseY=parseInt(e.clientY-offsetY);
    
            // account for the window scrolling
            var scrollX=$(window).scrollLeft();
            var scrollY=$(window).scrollTop();
    
            // see if we clicked on any targets
            for(var i=0;i<circles.length;i++){
                var circle=circles[i];
                var dx=(circle.x-scrollX)-mouseX;
                var dy=(circle.y-scrollY)-mouseY;
                var radius=circle.radius;
                // true if we clicked in the target circle
                if(dx*dx+dy*dy<=radius*radius){
                    drawBalloon(circles[i].x+radius,circles[i].y-100,circles[i].info);
                }
            }
        });
    
    
        // listen for clicks on the balloon and then hide the balloon
        $("#balloon").click(function(e){ $("#balloon").hide(); });
    
        // listen for scrolls and then hide the balloon
        $(window).scroll(function(e){
            $("#balloon").hide(); 
        });
    
    
        function drawCircle(circle){
            ctx.save();
            ctx.beginPath();
            ctx.fillStyle=circle.color;
            ctx.strokeStyle="black";
            ctx.lineWidth=3;
            ctx.arc(circle.x,circle.y,circle.radius,0,Math.PI*2,false);
            ctx.closePath();
            ctx.fill();
            ctx.stroke();
            ctx.restore();
        }
    
    
        function drawBalloon(X,Y,theInfo){
            popCtx.save();
            popCtx.fillStyle="#FD0";
            popCtx.strokeStyle="#000";
            // draw the balloon
            popCtx.beginPath();
            popCtx.moveTo(52,02);
            popCtx.quadraticCurveTo(02,02,02,42);
            popCtx.quadraticCurveTo(02,77,27,77);
            popCtx.quadraticCurveTo(27,102,07,102);
            popCtx.quadraticCurveTo(37,102,42,77);
            popCtx.quadraticCurveTo(102,77,102,42);
            popCtx.quadraticCurveTo(102,02,52,02);
            popCtx.lineWidth=3;
            popCtx.stroke();
            popCtx.fill();
            // draw theInfo
            popCtx.font="10pt arial";
            popCtx.fillStyle="black";
            popCtx.fillText(theInfo,10,50);
            popCtx.restore();
            // move the balloon canvas to the target
            $("#balloon").css({left:offsetX+X, top:offsetY+Y});
            $("#balloon").show();
        }
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <canvas id="canvas" width=1950 height=300></canvas>
        <canvas id="balloon" width=105 height=105></canvas>
    </body>
    </html>