Reputation: 47
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
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
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