vogellatte
vogellatte

Reputation: 47

Adding Background on Canvas

So I have made some waves on a canvas. Now I would also like to add a background to make like a nice sunset with waves. But my problem occurs when I make ctx.fillRect to draw the background. As I need to clear the area around the bottom for the waves to work, the whole screen is being cleared. Therefore also clearing the background

whole code

        var c = document.getElementById("screen2");
        var ctx = c.getContext("2d");
        var cw = c.width = window.innerWidth;
        var ch = c.height = window.innerHeight;
        var cx = cw / 2,
            cy = ch / 2;
        var rad = Math.PI / 180;
        var w = window.innerWidth;
        var h = 100;
        var amplitude = h;
        var frequency = .01;
        var phi = 0;
        var frames = 0;
        var stopped = true;

        var gradientSky = ctx.createLinearGradient(0, ch / 2, 0, ch);
        gradientSky.addColorStop(0, "#C1274E");
        gradientSky.addColorStop(0.25, "#C344B7");
        gradientSky.addColorStop(0.5, "#B2244A");
        gradientSky.addColorStop(0.75, "#B2244A");
        gradientSky.addColorStop(1, "#B2244A");
        
        ctx.fillStyle = gradientSky;
        ctx.fillRect(0, 0, cw, ch);

        var gradientA = ctx.createLinearGradient(0, ch / 2, 0, ch);
        gradientA.addColorStop(0, "#7a88d9");
        gradientA.addColorStop(1, "#5a6bd0");

        var gradientB = ctx.createLinearGradient(0, ch / 2, 0, ch);
        gradientB.addColorStop(0, "#646593");
        gradientB.addColorStop(1, "#0f2460");
        
        

        ctx.lineWidth = 4;
        var step = 0;

        function drawWaves() {
            frames++;
            phi = frames / 88;
            ctx.clearRect(0, 0, cw, ch);
            ctx.beginPath();
            ctx.moveTo(0, ch);
            for (var x = 0; x < w; x++) {
                y = Math.sin(x * frequency + phi) * amplitude / 2 + amplitude / 2;
                //y = Math.cos(x * frequency + phi) * amplitude / 2 + amplitude / 2;
                ctx.lineTo(x, y + ch - 390 + Math.sin(step / 2) * 20); // setting it to the bottom of the page 100= lift

            }
            ctx.lineTo(w, ch);
            ctx.lineTo(0, ch);
            ctx.fillStyle = gradientA;
            ctx.fill();
            frames++;
            phi = frames / 60;

            ctx.beginPath();

            ctx.moveTo(0, ch);
            for (var x = 0; x < w; x++) {
                y = Math.sin(x * frequency + phi) * amplitude / 4 + amplitude / 4;
                //y = Math.cos(x * frequency + phi) * amplitude / 2 + amplitude / 2;
                ctx.lineTo(x, y + ch - 380 + Math.sin(step) * 20); // setting it to the bottom of the page 100= lift

            }
            ctx.lineTo(w, ch);
            ctx.lineTo(0, ch);
            ctx.fillStyle = gradientB;
            ctx.fill();
            step += 0.02;
            requestId = window.requestAnimationFrame(drawWaves);
        }

        requestId = window.requestAnimationFrame(drawWaves);

I'm pretty sure that has to do what x and y coordinates I inserted into the ctx.fillRect(); and ctx.clearRect();. But I have tried all variants I could think of but still nothing works. Sometimes I get the Background to appear but then the clear tag wont clear the waves properly. Just for better understanding the ch and cw are window.innerHeight and window.innerWidth although this can also be seen in the code.

Upvotes: 0

Views: 34

Answers (1)

obscure
obscure

Reputation: 12891

The trick here is really simple. As most background images, your sunset also should fill the whole screen and will later be covered by the waves and ultimately the bubbles. This is how a painter would draw a painting. Since the background covers the whole canvas, you even don't need to clear it before because this is essentially being done by filling the canvas with the background.

So all you need to change is remove the clearReact() call and replace it by a fillRect(0,0,cw,ch) after setting the fillStyle to gradientSky.

Here's your modified example:

// Author: 
// Name: 
// URL: https://jsfiddle.net/7z2yh3pg/

function Blasen() {
  const section = document.querySelector('#screen')
  const createElement = document.createElement('spawn')
  var size = Math.random() * 60;
  createElement.style.width = 30 + size + 'px';
  createElement.style.height = 30 + size + 'px';
  createElement.style.left = Math.random() * innerWidth + "px";
  section.appendChild(createElement);

  setTimeout(() => {
    createElement.remove()
  }, 600)
}

const Blaseninterval = setInterval(Blasen, 100)

var c = document.getElementById("screen2");
var ctx = c.getContext("2d");
var cw = c.width = window.innerWidth;
var ch = c.height = window.innerHeight;
var cx = cw / 2,
  cy = ch / 2;
var rad = Math.PI / 180;
var w = window.innerWidth;
var h = 100;
var amplitude = h;
var frequency = .01;
var phi = 0;
var frames = 0;
var stopped = true;

var gradientSky = ctx.createLinearGradient(0, 0, 0, ch);
gradientSky.addColorStop(0, "#C1274E");
gradientSky.addColorStop(0.25, "#C344B7");
gradientSky.addColorStop(0.5, "#B2244A");
gradientSky.addColorStop(0.75, "#B2244A");
gradientSky.addColorStop(1, "#B2244A");

ctx.fillStyle = gradientSky;
ctx.fill();

var gradientA = ctx.createLinearGradient(0, ch / 2, 0, ch);
gradientA.addColorStop(0, "#7a88d9");
gradientA.addColorStop(1, "#5a6bd0");

var gradientB = ctx.createLinearGradient(0, ch / 2, 0, ch);
gradientB.addColorStop(0, "#646593");
gradientB.addColorStop(1, "#0f2460");



ctx.lineWidth = 4;
var step = 0;

function drawWaves() {
  frames++;
  phi = frames / 88;
  ctx.fillStyle = gradientSky;
  ctx.beginPath();
  ctx.rect(0, 0, cw, ch);
  ctx.closePath();
  ctx.fill();
  ctx.beginPath();
  ctx.moveTo(0, ch);
  for (var x = 0; x < w; x++) {
    y = Math.sin(x * frequency + phi) * amplitude / 2 + amplitude / 2;
    //y = Math.cos(x * frequency + phi) * amplitude / 2 + amplitude / 2;
    ctx.lineTo(x, y + ch - 250 + Math.sin(step / 2) * 20); // setting it to the bottom of the page 100= lift

  }
  ctx.lineTo(w, ch);
  ctx.lineTo(0, ch);
  ctx.fillStyle = gradientA;
  ctx.fill();
  frames++;
  phi = frames / 60;

  ctx.beginPath();

  ctx.moveTo(0, ch);
  for (var x = 0; x < w; x++) {
    y = Math.sin(x * frequency + phi) * amplitude / 4 + amplitude / 4;
    //y = Math.cos(x * frequency + phi) * amplitude / 2 + amplitude / 2;
    ctx.lineTo(x, y + ch - 240 + Math.sin(step) * 20); // setting it to the bottom of the page 100= lift

  }
  ctx.lineTo(w, ch);
  ctx.lineTo(0, ch);
  ctx.fillStyle = gradientB;
  ctx.fill();
  step += 0.02;
  requestId = window.requestAnimationFrame(drawWaves);
}

requestId = window.requestAnimationFrame(drawWaves);
body,
html {
  margin: 0;
  padding: 0;
  overflow: hidden;
}

canvas {
  display: block;
  margin: 0 auto;
  width: 100%;
  height: 100vh;
}

#screen {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}

#screen spawn {
  position: absolute;
  bottom: -80px;
  background: transparent;
  border-radius: 50%;
  pointer-events: none;
  box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.5);
  animation: animate 3s linear infinite;
}

#screen spawn:before {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  transform: scale(0.25) translate(-70%, -70%);
  background: radial-gradient(#fff, transparent);
  opacity: 0.6;
  border-radius: 50%;
}

@keyframes animate {
  0% {
    transform: translateY(0%);
    opacity: 1;
  }
  99% {
    opacity: 1;
  }
  100% {
    transform: translateY(-2000%);
    opacity: 0;
  }
}
<canvas id="screen2"></canvas>
<div id="screen"></div>

Upvotes: 1

Related Questions