最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Stacking multiple canvases in HTML5 - Stack Overflow

programmeradmin4浏览0评论

I am trying to use four canvases stacked upon eachother but the contents of them won't display besides the contents of the one on the top. I put z-index values to them in order in which I'd like them to display but only the top one is displaying the contents. Their position is absolute and their z indexes are 1, 2, 3 and 4. Is there anything more to it that makes them not display? Or, how many canvases could I stack together in order for all of their contents to display?

I have this:

<div></div>
<canvas id="bg" width="500" height="500"></canvas> <!--z-index:1 -->
<canvas id="lc" width="500" height="500"></canvas> <!--z-index:2 -->
<canvas id="rc" width="500" height="500"></canvas> <!--z-index:3 -->
<canvas id="ch" width="500" height="500"></canvas> <!--z-index:4 -->
<!-- Script that draws image in each canvas with different x and y values -->

The problem is that when I run the function, the picture I am drawing only appears once, which means it only drew it on one canvas... For example, I'll have the script something like this:

function drawImgs() {
    var bg = document.getElementById('bg').getContext('2d'),
        lc = document.getElementById('lc').getContext('2d'),
        rc = document.getElementById('rc').getContext('2d'),
        ch = document.getElementById('ch').getContext('2d'),
        img = new Image();
    img.src = "image.png";
    bg.drawImage(img,0,0);
    lc.drawImage(img,64,64);
    rc.drawImage(img,128,128);
    ch.drawImage(img,192,192);
}
drawImgs();

It will only draw the image on the ch canvas, at X:192, Y:192. Why is that? Is there a way to prevent it or at least make sure that all the images are drawn? Is it because I'm using the same image or are the canvasses just not being transparent? Is there a limit to how many canvasses you can look through?

Edit: However, if I only have two canvasses, both images render. Why is this? Couldn't at least two images render if I have four canvasses stacked together?

Edit: I was messing around with the code that I recieved from you guys (thanks for all the information, everything helped) and I tried to put it into my actual project (I tested the code and it was working before I put it into my project) but the once I put it into my files, it stopped working again. So I messed around and I noticed that when I didn't add CSS to make the page pretty that it would work... I kept messing around and I found out that the background-color of the canvas takes away the transparency, it was just that all along... So I just put it on the first canvas, bg, because my page is black and I wanted the canvas to be white.

I am trying to use four canvases stacked upon eachother but the contents of them won't display besides the contents of the one on the top. I put z-index values to them in order in which I'd like them to display but only the top one is displaying the contents. Their position is absolute and their z indexes are 1, 2, 3 and 4. Is there anything more to it that makes them not display? Or, how many canvases could I stack together in order for all of their contents to display?

I have this:

<div></div>
<canvas id="bg" width="500" height="500"></canvas> <!--z-index:1 -->
<canvas id="lc" width="500" height="500"></canvas> <!--z-index:2 -->
<canvas id="rc" width="500" height="500"></canvas> <!--z-index:3 -->
<canvas id="ch" width="500" height="500"></canvas> <!--z-index:4 -->
<!-- Script that draws image in each canvas with different x and y values -->

The problem is that when I run the function, the picture I am drawing only appears once, which means it only drew it on one canvas... For example, I'll have the script something like this:

function drawImgs() {
    var bg = document.getElementById('bg').getContext('2d'),
        lc = document.getElementById('lc').getContext('2d'),
        rc = document.getElementById('rc').getContext('2d'),
        ch = document.getElementById('ch').getContext('2d'),
        img = new Image();
    img.src = "image.png";
    bg.drawImage(img,0,0);
    lc.drawImage(img,64,64);
    rc.drawImage(img,128,128);
    ch.drawImage(img,192,192);
}
drawImgs();

It will only draw the image on the ch canvas, at X:192, Y:192. Why is that? Is there a way to prevent it or at least make sure that all the images are drawn? Is it because I'm using the same image or are the canvasses just not being transparent? Is there a limit to how many canvasses you can look through?

Edit: However, if I only have two canvasses, both images render. Why is this? Couldn't at least two images render if I have four canvasses stacked together?

Edit: I was messing around with the code that I recieved from you guys (thanks for all the information, everything helped) and I tried to put it into my actual project (I tested the code and it was working before I put it into my project) but the once I put it into my files, it stopped working again. So I messed around and I noticed that when I didn't add CSS to make the page pretty that it would work... I kept messing around and I found out that the background-color of the canvas takes away the transparency, it was just that all along... So I just put it on the first canvas, bg, because my page is black and I wanted the canvas to be white.

Share Improve this question edited Apr 5, 2018 at 10:53 Cœur 38.8k25 gold badges205 silver badges277 bronze badges asked Jan 4, 2014 at 1:01 user2673553user2673553 3615 silver badges11 bronze badges 6
  • While I admit I'm having problems with jsfiddle, the problems I'm having are not the ones you're experiencing(hit run again if nothing shows). – Daedalus Commented Jan 4, 2014 at 1:20
  • Edit your fiddle and ment out the two middle canvasses and drawImage calls (lc,rc) and the images will render... – user2673553 Commented Jan 4, 2014 at 1:27
  • You're missing my point. I also just tried that; it doesn't fix the fiddle. Like I said; it works fine if you just hit run again. – Daedalus Commented Jan 4, 2014 at 1:28
  • I know what you're trying to say. And does it have to do something with loading the canvas or something? I see that it worked if you hit run again, how could I apply that to an html file though? – user2673553 Commented Jan 4, 2014 at 1:35
  • Firstly, are you running this on a local server? – Daedalus Commented Jan 4, 2014 at 1:37
 |  Show 1 more ment

3 Answers 3

Reset to default 3

First step is to wrap your canvases into a container:

<div id="stack">
    <canvas id="bg" width="500" height="500"></canvas>
    <canvas id="lc" width="500" height="500"></canvas>
    <canvas id="rc" width="500" height="500"></canvas>
    <canvas id="ch" width="500" height="500"></canvas>
<div>

then properly apply CSS rules:

#stack {
    position:relative;
    }
#stack > canvas {
    position:absolute;
    left:0;
    top:0;
    }

z-index is not necessary here as the first canvas will be at the bottom etc.

Next is to implement a image loader handler as image loading is asynchronous. This is the reason why your image doesn't show as the image hasn't finished loading before calling drawImage() (at the time the code gets to the "fourth" element the image may be loaded depending on various factors such as cache, system performance etc - but this is in the category "random result":

var bg = document.getElementById('bg').getContext('2d'),
    lc = document.getElementById('lc').getContext('2d'),
    rc = document.getElementById('rc').getContext('2d'),
    ch = document.getElementById('ch').getContext('2d'),
    img = new Image();

img.onload = drawImgs;    /// set handler
img.src = "image.png";    /// set url

function drawImgs() {
    /// 'this' is the loaded image
    bg.drawImage(this, 0,0);
    lc.drawImage(this, 64,64);
    rc.drawImage(this, 128,128);
    ch.drawImage(this, 192,192);

    /// continue rest of code here...
}

If you put your script at the bottom of your page then that's it. If in the header wrap your script in:

window.onload = function() {

    ... code above here...
}

Other considerations is that your image gets loaded properly. For that you can use the onerror and onabort handlers on the image object:

img.onerror = functionToHandleError;
img.onabort = functionToHandleAbort;

also these defined before setting the src property.

Make sure you use CSS to stack each canvas on top of each other

canvas{position:absolute;border:1px solid red;}

Make sure you give your image time to load

var img=new Image();
img.onload=function(){
    bg.drawImage(img,0,0);
    lc.drawImage(img,64,64);
    rc.drawImage(img,128,128);
    ch.drawImage(img,192,192);
}
img.src="img.png";

Here's an example:

<!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./jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    #wrapper{position:relative;}
    canvas{position:absolute;border:1px solid red;}
</style>

<script>
window.onload=function(){


    var ctxs=[];
    for(var i=0;i<5;i++){
        ctxs.push(document.getElementById("canvas"+i).getContext("2d"));
        ctxs[i].fillStyle="black";
        ctxs[i].font="12px verdana";
        ctxs[i].fillRect(50,i*30+20,100,20);
        ctxs[i].fillStyle="white";
        ctxs[i].fillText("canvas#"+i,60,i*30+35);
    };

}
</script>

</head>

<body>
    <div id="wrapper">
        <canvas id="canvas0" width=300 height=300></canvas>
        <canvas id="canvas1" width=300 height=300></canvas>
        <canvas id="canvas2" width=300 height=300></canvas>
        <canvas id="canvas3" width=300 height=300></canvas>
        <canvas id="canvas4" width=300 height=300></canvas>
    </div>
</body>
</html>

One final thought: You might take a quick look at jQuery. It is an excellent utility library that does a great job of solving cross-browser inconsistencies. It is well-tested and in widespread use so your user might already have it cached on their machine.

Canvases can be transparent; I've used this method before. I put up a JSFiddle that you can check to make sure your browser hasn't gone wacky; I'm using the same method you are in your example code, just drawing a square instead of an image. I think the problem is something else.

<canvas id="top" height=100 width=100></canvas>
<canvas id="tall" height=100 width=100></canvas>
<canvas id="short" height=100 width=100></canvas>
<canvas id="bottom" height=100 width=100></canvas>

and JS

var top = document.getElementById("top").getContext("2d");
var tall = document.getElementById("tall").getContext("2d");
var short = document.getElementById("short").getContext("2d");
var bottom = document.getElementById("bottom").getContext("2d");

top.fillRect(0,0,10,10);
tall.fillRect(20,20,10,10);
short.fillRect(40,40,10,10);
bottom.fillRect(60,60,10,10);

To debug, I would just try drawing in each canvas individual, removing the others from your HTML, to make sure that you've got all your references right (it looks like you do.) Then, double-check your CSS and z-index to make sure you're not hiding an element somehow, either by not showing it, or putting its z-index behind another object. Finally, make sure that no other code somewhere is clearing out your canvases, or possibly drawing over your image (if it drew with the same color as your background, it would appear that the canvas was blank, when it was really full of the background color.)

发布评论

评论列表(0)

  1. 暂无评论