Canvas를 3개의 레이어(Layer)로 나눴습니다. 첫번째(밑) 레이어에는 배경색을 넣고, 세번째(위) 레이어에는 체크무늬 선을 넣었습니다. 가운데 레이어에는 파란색 공을 그리고 애니메이션을 주어서 움직이게 했습니다. 첫번째와 세번째 레이어는 처음에 한번만 그려주고, 가운데 레이어만 갱신해주었습니다. 세개의 레이어가 겹쳐서 보여집니다.
<!DOCTYPE html>
<style>
#myDiv {
display: inline-block; position: relative;
border: 5px solid gray;
}
#myDiv canvas { max-width: 100%; }
#layer1 { vertical-align: top; z-index: 1; }
#layer2 { position: absolute; left: 0; top: 0; z-index: 2; }
#layer3 { position: absolute; left: 0; top: 0; z-index: 3; }
</style>
<div id="myDiv">
<canvas id="layer1" width="400" height="300"></canvas>
<canvas id="layer2" width="400" height="300"></canvas>
<canvas id="layer3" width="400" height="300"></canvas>
</div>
<script>
const WIDTH = 400;
const HEIGHT = 300;
var ctx1 = document.getElementById("layer1").getContext("2d");
var grad = ctx1.createLinearGradient(0, 0, WIDTH, HEIGHT);
grad.addColorStop(0, "white");
grad.addColorStop(1, "hotpink");
ctx1.fillStyle = grad;
ctx1.fillRect(0, 0, WIDTH, HEIGHT);
var ctx3 = document.getElementById("layer3").getContext("2d");
ctx3.lineWidth = 5;
ctx3.strokeStyle = "rgba(100,100,100,0.5)";
for (var i = 50; i < WIDTH; i+=50) {
ctx3.beginPath();
ctx3.moveTo(i, 10);
ctx3.lineTo(i, HEIGHT - 10);
ctx3.stroke();
}
for (var i = 50; i < HEIGHT; i+=50) {
ctx3.beginPath();
ctx3.moveTo(10, i);
ctx3.lineTo(WIDTH - 10, i);
ctx3.stroke();
}
var ctx = document.getElementById("layer2").getContext("2d");
ctx.fillStyle = "dodgerblue";
var x = 100, y = 100;
var radius = 30;
var mx = Math.random() * 3 + 2;
var my = Math.random() * 3 + 2;
function ballMove() {
x += mx;
y += my;
if (x - radius < 0 && mx < 0) mx *= -1;
if (x + radius > WIDTH && mx > 0) mx *= -1;
if (y - radius < 0 && my < 0) my *= -1;
if (y + radius > HEIGHT && my > 0) my *= -1;
ctx.clearRect(0, 0, WIDTH, HEIGHT);
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fill();
requestAnimationFrame(ballMove);
}
ballMove();
</script>