
canvas 하나만으로 벚꽃잎을 흩날려야 할 일이 생겼다.
- 벚꽃잎 이미지 없음. (알아서 그려주면 좋겠음)
- 벚꽃잎 사이즈 랜덤, 색상은 주어진 색상들 중에 랜덤이면 좋겠음
- 기왕이면 좀 더 리얼하게 flip 하는 효과가 있음 좋겠음
- 벚꽃잎이 날리는 방향도 초기에 설정할 수 있음 좋겠음. (여기선 우상단 > 좌하단)
Gemini로 프롬프트 넣어서 작성하였고, 재사용 쉽도록 class로 묶었습니다.
See the Pen cherry blossom petals by Oh Ikmyeong (@dpffpself) on CodePen.
HTML,CSS
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>벚꽃잎 날리기 정리좀 함</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #f0f0f0;
}
/* 캔버스는 투명하게, 화면 전체를 채움 */
#cherry-blossom-canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
/* 클릭 방해 금지 */
}
</style>
<script src="./js/main.js" type="module"></script>
</head>
<body>
<canvas id="cherry-blossom-canvas"></canvas>
</body>
</html>
|
cs |
main.js
|
1
2
3
|
import { PetalCtrl } from "./PetalCtrl.js";
new PetalCtrl().init();
|
cs |
Petal.js
꽃잎을 개별로 그리고 움직이는 클래스
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
/**
* 벚꽃잎 생성자
*/
export class Petal {
constructor() {
}
set_canvas($canvas) {
this.$canvas = $canvas;
return this;
}
set_ctx(ctx) {
this.ctx = ctx;
return this;
}
set_colors(COLORS) {
this.COLORS = COLORS;
return this;
}
init() {
// 우측 상단 영역에서 시작하도록 설정
this.x = Math.random() * (this.$canvas.width * 1.5);
this.y = Math.random() * this.$canvas.height * -1; // 화면 위쪽에서 생성
this.size = Math.random() * 5 + 5; // 크기 5~10
this.color = this.COLORS[Math.floor(Math.random() * this.COLORS.length)];
// 이동 속도 (우상단 -> 좌하단)
this.horizontalSpeed = Math.random() * -2 - 1; // 왼쪽으로 이동
this.verticalSpeed = Math.random() * 2 + 1; // 아래로 이동
this.opacity = Math.random() * 0.5 + 0.3;
this.flip = Math.random(); // 팔랑거리는 효과를 위한 변수
this.flipSpeed = Math.random() * 0.03;
/* 최종 */
return this;
}
update() {
this.x += this.horizontalSpeed;
this.y += this.verticalSpeed;
this.flip += this.flipSpeed;
// 화면 밖으로 완전히 벗어나면 다시 생성 (Infinite Loop)
if (this.y > this.$canvas.height || this.x < -this.size) {
this.init();
}
}
draw() {
if (this.y < -this.size || this.x > this.$canvas.width + this.size) return;
this.ctx.save();
this.ctx.beginPath();
this.ctx.translate(this.x, this.y);
// 팔랑거리는 회전 효과
this.ctx.rotate(this.flip);
this.ctx.scale(Math.sin(this.flip), 1);
// 벚꽃잎 모양 그리기
this.ctx.fillStyle = this.color;
this.ctx.globalAlpha = this.opacity;
// 단순 원형이 아닌 타원형으로 잎 표현
this.ctx.moveTo(0, 0);
this.ctx.bezierCurveTo(-this.size, -this.size, -this.size, this.size, 0, this.size);
this.ctx.bezierCurveTo(this.size, this.size, this.size, -this.size, 0, 0);
this.ctx.fill();
this.ctx.restore();
}
}//class:Petal
|
cs |
PetalCtrl.js
캔버스 전체 관장
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
import { Petal } from "./Petal.js";
export class PetalCtrl {
constructor() {
/* DOM */
this.$canvas = document.getElementById('cherry-blossom-canvas');
this.ctx = this.$canvas.getContext('2d');
/* 설정 변수 */
this.TOTAL_PETALS = 50;
this.COLORS = ['#FFC0CB', '#FFB7C5', '#FFA1B2'];
this.petals = [];
/* 타이머 */
this.resizeTimer = null;
}
/**
*
*/
init() {
/* 리사이즈 */
this.on_resize();
window.addEventListener('resize', () => {
/* 타이머 취소 */
clearTimeout(this.resizeTimer);
this.resizeTimer = setTimeout(() => {
this.on_resize();
}, 300);
});
/* 꽃잎들을 생성하고 */
this.create_petals();
/* 움직이기 */
this.animate();
}//init
/**
* 윈도우 크기 변경시
*/
on_resize = () => {
this.$canvas.width = window.innerWidth;
this.$canvas.height = window.innerHeight;
}//on_resize
/**
* 초기 벚꽃잎들 생성
*/
create_petals = () => {
for (let i = 0; i < this.TOTAL_PETALS; i++) {
this.petals.push(
new Petal()
.set_colors(this.COLORS)
.set_canvas(this.$canvas)
.set_ctx(this.ctx)
.init()
);//push
}//for
}//create_petals
/**
* 움직이기 시작
*/
animate = () => {
// 배경을 투명하게 유지하기 위해 이전 프레임을 지움
this.ctx.clearRect(0, 0, this.$canvas.width, this.$canvas.height);
this.petals.forEach(petal => {
petal.update();
petal.draw();
});
requestAnimationFrame(this.animate);
}//animate
}//PetalCtrl
|
cs |
'CSS&JS > ⚡Thinkers' 카테고리의 다른 글
| [JS] 값 입력 받아서 JS로 svg 꺾은선 그래프 그리기 (0) | 2026.04.03 |
|---|---|
| [CSS,JS] 24시간 쿠키, 드래그 가능한 레이어 팝업CSS,JS] 24시간 쿠키, 드래그 가능한 레이어 팝업 (0) | 2026.03.20 |
| [JS] canvas로 video 크로마키 하기 (0) | 2026.03.11 |
| [JS] canvas로 첨부파일 이미지로부터 평균 배경색상 추출해서 4사분면 그라디언트 (0) | 2026.03.09 |
| [JS] 첨부한 이미지 파일의 평균 색상값 구하기 (0) | 2026.03.09 |