1

I am trying to use this example: http://html5.litten.com/using-multiple-html5-canvases-as-layers/ to create multiple html5 layers (Actually only need 2) for a background and then an animation on top of that background.

The problem is the example, and many other solutions that suggest layering canvases using z-index, etc. all seem to position the canvas at left:0 and top:0 in absolute position.

For example: html5 - canvas element - Multiple layers html5 - canvas element - Multiple layers

However, what I would like to do, is have the position be dynamic but always so the two canvases are layered on top of each other.

What I've had to do so far is this:

    <div id="canvasesdiv" align=center; style="text-align:center; float:center">
        <canvas id="bottomlayer-background" style="z-index: 1; border:1px dotted;" align=center>
        This text is displayed if your browser does not support HTML5 Canvas.
        </canvas>
        <canvas id="toplayer-movingstuff" style="z-index: 2; border:1px dotted; position:absolute; left:530px; top:83px">
        This text is displayed if your browser does not support HTML5 Canvas.
        </canvas>
</div>  

The problem with this approach is that I had to manually figure out where the top left of the bottom layer was and then input that into the top layer. But this position is only true for one browser, on one monitor, on full screen, etc. Obviously, not workable.

When I try and have both just be align=center, then what happens is the canvases appear side-by-side instead of layered on top of each other.

When I try to do absolute position for both, the problem with that is the other stuff in the windows, that were originally below the canvases (i.e. text, tables, etc.) suddenly appear underneath the canvases.

Has anyone else been able to solve this problem?

Thanks!

Community
  • 1
  • 1
user1031885
  • 63
  • 1
  • 7

2 Answers2

3

The way that absolute positioning works is that the target element is absolutely positioned within its closest positioned ancestor. This means that if the containing div is positioned absolute or relative, then the target element will be absolutely positioned within the containing div.

Note: You don't really need the z-index unless you've messed with z-index somewhere else

Another Note: If you want your canvases to behave, set the width and height attributes on them, otherwise things will scale weird.

http://jsfiddle.net/mobidevelop/4WDJz/

HTML

<p>Other Content</p>
<p>Other Content</p>
<p>Other Content</p>

<div id="contain">
        <canvas id="surface1" width="480" height="160">
        </canvas>
        <canvas id="surface2" width="480" height="160">
        </canvas>
</div>

<p>Other Content</p>
<p>Other Content</p>
<p>Other Content</p>​

CSS:

#contain {
    width: 480px;
    height: 160px;
    margin: 0 auto;
    position: relative;    
}

#surface1,
#surface2 {
    top: 0;
    left: 0;
    position: absolute;
}

​And, for good measure, JS:

var surface1 = document.getElementById('surface1');
if (surface1 != null) {
    if (surface1.getContext) {
        var context = surface1.getContext("2d");
        if (context != null) {
            context.fillStyle = "rgba(255,0,0,0.25)";
            context.fillRect(0,0,480,160);
        }
    }
}
surface2 = document.getElementById('surface2');
if (surface2 != null) {
    if (surface2.getContext) {
        var context = surface2.getContext("2d");
        if (context != null) {
            var x = 0;
            context.fillStyle = "rgba(0,0,0,1.0)";
            last = new Date();
            setInterval
            (
                function()
                {
                    var now = new Date();
                    var del = (now - last) / 1000.0
                    last = now;

                    context.clearRect(0,0, 480, 160);
                    context.fillRect(x, 10,32,32);                
                    x += 10 * del;
                    if (x > 480) {
                        x = -32;
                    }
                }, 15
            );            

        }
    }
}

nEx.Software
  • 6,782
  • 1
  • 26
  • 34
  • Ahh, a reason why I don't set the height and width is because I'm determining those dynamically using javascript right now because I want to be able to adjust the # of rows and columns on my grid which can potentially change the size of the canvas. Is there any way to do this without having to set the width and height ahead of time? – user1031885 Jul 01 '12 at 05:58
  • As long as you set the width and height attributes on the canvas element and not the css you should be fine. Just remember to redraw the background layer if it changes at run time. See this update to the previous fiddle to see the difference: http://jsfiddle.net/4WDJz/6/ – nEx.Software Jul 01 '12 at 13:32
  • (Note: I am setting the size proportionately, so the weird scaling isn't totally obvious, but if you try something non proportional you'll see the scaling problem). – nEx.Software Jul 01 '12 at 13:38
  • This is almost working for me. I'm using the set default example that you used above, and the canvases are now both centered together. The issue now is that canvas appears about a tenth or so smaller than it originally was when I was setting it. It's similar to when your CSS or HTML example how everything is smaller, except unlike you, I'm not purposefully making it smaller. my width and height don't say "px" but everything on my canvas now appears smaller? – user1031885 Jul 01 '12 at 14:52
  • Also, I still have the problem of all the text that I have on the page that's not in the canvas is still on a layer below the canvas rather than being underneath the canvas on the page. Do you know how to fix that? – user1031885 Jul 01 '12 at 14:52
  • I think I'd have to see an example to know what you mean, could you make a fiddle? – nEx.Software Jul 01 '12 at 14:57
  • So, basically I set the height and width of the div, but it never changes and then the canvases are oddly shaped and everything overlays the table I have there and it's not centered. – user1031885 Jul 01 '12 at 17:01
  • Did you mean to paste a different jsfiddle url? That's the one I sent you. – nEx.Software Jul 01 '12 at 17:17
  • Ooops, sorry was working off of yours too :) http://jsfiddle.net/cousinwillie/KxYVG/16/ – user1031885 Jul 01 '12 at 17:28
  • A couple things: 1) You don't want to set the style.width and style.height of the canvases, but you will want to set them for the containing div after determining how big the canvases will be. This will push the surrounding content below the canvases. 2) You want both canvases to be absolutely positioned. Fixing those things should get the right results. For fun I took your concept and built out something similar but not the same (I don't want to rob you of your work/learning). You can find it at http://jsfiddle.net/mobidevelop/dDEAN/ if you want to check it out. – nEx.Software Jul 01 '12 at 21:10
  • It worked! The only thing now is that unfortunately you can't seem to dynamically assign z-index from javascript. In your other example you used settimeout for the animation. I think that is the slightly older method of animation? I am using requestAnimationFrame but not sure if you can help with that one as well http://stackoverflow.com/questions/11265019/using-clearrect-in-requestanimationframe-does-not-show-the-animation – user1031885 Jul 01 '12 at 22:44
  • Yeah, setInterval is the older more universal method. You should be able to set z-index by JavaScript with this one. I'll check out your other. – nEx.Software Jul 01 '12 at 23:48
0
#canvasesdiv{margin:0 auto; position:relative; width:300px;}

#bottomlayer-background, #toplayer-movingstuff{
    position:absolute; 
    z-index: 1; 
    border:1px dotted blue; 
    height:200px;
    width:300px;
}
#toplayer-movingstuff{
    z-index: 2; 
    border:1px solid red; 
}

Working Fiddle

The above should work. Just give the containing element a relative position, which will make the child elements positioned with absolute relative to the parent.

Loktar
  • 34,764
  • 7
  • 90
  • 104
  • This is similar to the example above, but like the one above, I still have the same issues that the canvas now appears smaller and the other text looks like it's layered underneath the canvas rather than being actually down screen from the canvas. – user1031885 Jul 01 '12 at 14:53