learningtoanimate
learningtoanimate

Reputation: 934

Display Canvas behind DIV

This question title is relatively self explanatory. I'd like the canvas to be in the background of the page while the page's content starts where it normally would. I tried making a DIV for each with their own Z-index but this didn't do anything.

I need to figure out a way to send the canvas back, I've made the body background colour red so there only needs to be two layers (snow and content) rather than the three (background included).

I just need it so that the content displays on top as it would with any normal page, the snow should be a background element that goes along with the scrolling of the page.

    (function() {
    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame ||
    function(callback) {
        window.setTimeout(callback, 1000 / 60);
    };
    window.requestAnimationFrame = requestAnimationFrame;
})();


var flakes = [],
    canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    flakeCount = 400,
    mX = -100,
    mY = -100

    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

function snow() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    for (var i = 0; i < flakeCount; i++) {
        var flake = flakes[i],
            x = mX,
            y = mY,
            minDist = 150,
            x2 = flake.x,
            y2 = flake.y;

        var dist = Math.sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y)),
            dx = x2 - x,
            dy = y2 - y;

        if (dist < minDist) {
            var force = minDist / (dist * dist),
                xcomp = (x - x2) / dist,
                ycomp = (y - y2) / dist,
                deltaV = force / 2;

            flake.velX -= deltaV * xcomp;
            flake.velY -= deltaV * ycomp;

        } else {
            flake.velX *= .98;
            if (flake.velY <= flake.speed) {
                flake.velY = flake.speed
            }
            flake.velX += Math.cos(flake.step += .05) * flake.stepSize;
        }

        ctx.fillStyle = "rgba(255,255,255," + flake.opacity + ")";
        flake.y += flake.velY;
        flake.x += flake.velX;
            
        if (flake.y >= canvas.height || flake.y <= 0) {
            reset(flake);
        }


        if (flake.x >= canvas.width || flake.x <= 0) {
            reset(flake);
        }

        ctx.beginPath();
        ctx.arc(flake.x, flake.y, flake.size, 0, Math.PI * 2);
        ctx.fill();
    }
    requestAnimationFrame(snow);
};

function reset(flake) {
    flake.x = Math.floor(Math.random() * canvas.width);
    flake.y = 0;
    flake.size = (Math.random() * 3) + 2;
    flake.speed = (Math.random() * 1) + 0.5;
    flake.velY = flake.speed;
    flake.velX = 0;
    flake.opacity = (Math.random() * 0.5) + 0.3;
}

function init() {
    for (var i = 0; i < flakeCount; i++) {
        var x = Math.floor(Math.random() * canvas.width),
            y = Math.floor(Math.random() * canvas.height),
            size = (Math.random() * 3) + 2,
            speed = (Math.random() * 1) + 0.5,
            opacity = (Math.random() * 0.5) + 0.3;

        flakes.push({
            speed: speed,
            velY: speed,
            velX: 0,
            x: x,
            y: y,
            size: size,
            stepSize: (Math.random()) / 30,
            step: 0,
            opacity: opacity
        });
    }

    snow();
};

canvas.addEventListener("mousemove", function(e) {
    mX = e.clientX,
    mY = e.clientY
});

window.addEventListener("resize",function(){
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
})

init();
body, html{
  margin:0;
  padding:0;
  overflow-x: hidden;
  user-select: none;
  -moz-appearance: none;
  -webkit-appearance: none;
  background-color: #E71D36;
}

.page {
    min-width: 100%;
    max-width: 100%;
    z-index: -1;
}

.contentwrap {
    min-width: 100%;
    max-width: 100%;
    z-index: 1;
}

.content {
    min-width: 50%;
    max-width: 50%;
    margin-left: auto;
    margin-right: auto;
    text-align: center;
    z-index: 1;
}

@media only screen and (max-width: 500px) {
.content {
    min-width: 90%;
    max-width: 90%;
    margin-left: auto;
    margin-right: auto;
    text-align: center;
    z-index: 1;
}
}

.canvas-holder {
    z-index: 0;
}

.canvas {
    z-index: -1;
}
<div class="page">
<div class-"canvas-holder">
<canvas id="canvas">
</canvas>
</div>
<div class="content">
<h1>Content is below the canvas</h1>
</div>
</div>

Any tips would be appreciated.

Upvotes: 3

Views: 2568

Answers (1)

haldo
haldo

Reputation: 16691

Use position: absolute for the canvas and content. I've made some other changes to .content css to center the text (and added class="canvas" to the canvas html). I also removed z-index as it's not needed if you use absolute positioning.

You asked in a comment:

Any ideas how to make the canvas the height of the page, not just the window. That'd be appreciated too

One option is to use position: fixed which will keep the canvas position fixed as the page scrolls.

Please see updated snippet.

(function() {
    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame ||
    function(callback) {
        window.setTimeout(callback, 1000 / 60);
    };
    window.requestAnimationFrame = requestAnimationFrame;
})();


var flakes = [],
    canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    flakeCount = 400,
    mX = -100,
    mY = -100

    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

function snow() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    for (var i = 0; i < flakeCount; i++) {
        var flake = flakes[i],
            x = mX,
            y = mY,
            minDist = 150,
            x2 = flake.x,
            y2 = flake.y;

        var dist = Math.sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y)),
            dx = x2 - x,
            dy = y2 - y;

        if (dist < minDist) {
            var force = minDist / (dist * dist),
                xcomp = (x - x2) / dist,
                ycomp = (y - y2) / dist,
                deltaV = force / 2;

            flake.velX -= deltaV * xcomp;
            flake.velY -= deltaV * ycomp;

        } else {
            flake.velX *= .98;
            if (flake.velY <= flake.speed) {
                flake.velY = flake.speed
            }
            flake.velX += Math.cos(flake.step += .05) * flake.stepSize;
        }

        ctx.fillStyle = "rgba(255,255,255," + flake.opacity + ")";
        flake.y += flake.velY;
        flake.x += flake.velX;
            
        if (flake.y >= canvas.height || flake.y <= 0) {
            reset(flake);
        }


        if (flake.x >= canvas.width || flake.x <= 0) {
            reset(flake);
        }

        ctx.beginPath();
        ctx.arc(flake.x, flake.y, flake.size, 0, Math.PI * 2);
        ctx.fill();
    }
    requestAnimationFrame(snow);
};

function reset(flake) {
    flake.x = Math.floor(Math.random() * canvas.width);
    flake.y = 0;
    flake.size = (Math.random() * 3) + 2;
    flake.speed = (Math.random() * 1) + 0.5;
    flake.velY = flake.speed;
    flake.velX = 0;
    flake.opacity = (Math.random() * 0.5) + 0.3;
}

function init() {
    for (var i = 0; i < flakeCount; i++) {
        var x = Math.floor(Math.random() * canvas.width),
            y = Math.floor(Math.random() * canvas.height),
            size = (Math.random() * 3) + 2,
            speed = (Math.random() * 1) + 0.5,
            opacity = (Math.random() * 0.5) + 0.3;

        flakes.push({
            speed: speed,
            velY: speed,
            velX: 0,
            x: x,
            y: y,
            size: size,
            stepSize: (Math.random()) / 30,
            step: 0,
            opacity: opacity
        });
    }

    snow();
};

canvas.addEventListener("mousemove", function(e) {
    mX = e.clientX,
    mY = e.clientY
});

window.addEventListener("resize",function(){
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
})

init();
body, html{
  margin:0;
  padding:0;
  overflow-x: hidden;
  user-select: none;
  -moz-appearance: none;
  -webkit-appearance: none;
  background-color: #E71D36;
}

.page {
    min-width: 100%;
    max-width: 100%;
}

.contentwrap {
    min-width: 100%;
    max-width: 100%;
}

.content {
    min-width: 100%;
    max-width: 100%;
    margin-left: auto;
    margin-right: auto;
    text-align: center;
    position: absolute;
    left: 0;
    right: 0;
}

@media only screen and (max-width: 500px) {
.content {
    min-width: 90%;
    max-width: 90%;
    margin-left: auto;
    margin-right: auto;
    text-align: center;
}
}

.canvas-holder {
}

.canvas {
    position: fixed;
}
<div class="page">
  <div class="canvas-holder">
    <canvas id="canvas" class="canvas">
    </canvas>
  </div>
  <div class="content">
    <h1>Content is below the canvas</h1>
    <p style="height: 900px;"></p>
  </div>
</div>

Upvotes: 3

Related Questions