답변 5개
단순 위에서 아래로 중력에 의한 오브젝트 정렬이라면
</p>
<p><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Falling Circles Simulation</title>
<style>
body {
margin: 0;
overflow: hidden;
}
canvas {
display: block;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const circles = [];
const numCircles = 6;
const gravity = 0.1;
const friction = 0.99;
const minRadius = 10;
const maxRadius = 100;
const canvasWidth = 500;
const canvasHeight = 500;
const boxHeight = 100;</p>
<p> canvas.width = canvasWidth;
canvas.height = canvasHeight;</p>
<p> class Circle {
constructor(x, y, radius, vx = 0, vy = 0) {
this.x = x;
this.y = y;
this.radius = radius;
this.vx = vx;
this.vy = vy;
}</p>
<p> draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(0, 150, 255, 0.7)';
ctx.fill();
ctx.strokeStyle = 'rgba(0, 100, 200, 0.9)';
ctx.stroke();
}</p>
<p> update() {
this.vy += gravity;
this.vx *= friction;
this.vy *= friction;
this.x += this.vx;
this.y += this.vy;</p>
<p> if (this.x + this.radius > canvasWidth) {
this.x = canvasWidth - this.radius;
this.vx *= -0.8;
}
if (this.x - this.radius < 0) {
this.x = this.radius;
this.vx *= -0.8;
}
if (this.y + this.radius > canvasHeight - boxHeight) {
this.y = canvasHeight - boxHeight - this.radius;
this.vy *= -0.8;
}</p>
<p> for (const other of circles) {
if (other !== this) {
const dx = this.x - other.x;
const dy = this.y - other.y;
const distance = Math.sqrt(dx * dx + dy * dy);
const minDistance = this.radius + other.radius;</p>
<p> if (distance < minDistance) {
const angle = Math.atan2(dy, dx);
const overlap = minDistance - distance;</p>
<p> // Separate the circles
this.x += Math.cos(angle) * (overlap / 2);
this.y += Math.sin(angle) * (overlap / 2);
other.x -= Math.cos(angle) * (overlap / 2);
other.y -= Math.sin(angle) * (overlap / 2);</p>
<p> // Simple collision response
const normalX = dx / distance;
const normalY = dy / distance;
const relativeVelocityX = this.vx - other.vx;
const relativeVelocityY = this.vy - other.vy;
const dotProduct = (relativeVelocityX * normalX) + (relativeVelocityY * normalY);</p>
<p> if (dotProduct > 0) {
const coefficientOfRestitution = 0.8; // Bounciness factor
const massSum = this.radius + other.radius;
const impulse = (2 * dotProduct) / massSum;</p>
<p> this.vx -= impulse * other.radius * normalX;
this.vy -= impulse * other.radius * normalY;
other.vx += impulse * this.radius * normalX;
other.vy += impulse * this.radius * normalY;
}
}
}
}
}
}</p>
<p> function generateRandomCircle() {
const radius = Math.random() * (maxRadius - minRadius) + minRadius;
const x = Math.random() * (canvasWidth - radius * 2) + radius;
const y = Math.random() * -500 - radius;
const vx = (Math.random() - 0.5) * 2;
const vy = (Math.random() - 0.5) * 2;
return new Circle(x, y, radius, vx, vy);
}</p>
<p> function createCircles() {
for (let i = 0; i < numCircles; i++) {
circles.push(generateRandomCircle());
}
}</p>
<p> function drawBox() {
ctx.fillStyle = 'rgba(100, 100, 100, 0.5)';
ctx.fillRect(0, canvasHeight - boxHeight, canvasWidth, boxHeight);
}</p>
<p> function animate() {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
drawBox();
for (const circle of circles) {
circle.update();
circle.draw();
}
requestAnimationFrame(animate);
}</p>
<p> createCircles();
animate();
</script>
</body>
</html></p>
<p>

이정도면 될것 같은데 이게 단순 math로 구현하기엔 변수가 너무 많습니다.
별도 플러그인도 해외에서 찾아보면 있을것 같기도 한데
구글신에게 의뢰해보세요..
답변에 대한 댓글 3개
댓글을 작성하려면 로그인이 필요합니다.
</p>
<p><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Falling Circles Simulation</title>
<style>
body {
margin: 0;
overflow: hidden;
}
canvas {
display: block;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const circles = [];
const numCircles = 6; // 떨어질 오브젝트 갯수
const gravity = 0.1; // 적용될 중력
const friction = 0.99; // 낙하 가속도
const minRadius = 10; // 오브젝트 최소 크기
const maxRadius = 100; // 오브젝트 최대 크기
const canvasWidth = 500; // 캔바스 너비
const canvasHeight = 500; // 캔바스 높이
const boxHeight = 100; // border</p>
<p> const Circlestexts = ['하나', '둘', '셋', '넷', '다섯', '여섯']; // 오브젝트 갯수만큼 텍스트 배열
const Circlesbg = ['#fff100', '#cc0000', '#111111', '#444444', '#888888', '#000000']; // 오브젝트 갯수만큼 배경컬러 배열</p>
<p> canvas.width = canvasWidth;
canvas.height = canvasHeight;</p>
<p> class Circle {
constructor(x, y, radius, vx = 0, vy = 0, text = '', bgColor = '#fff') {
this.x = x;
this.y = y;
this.radius = radius;
this.vx = vx;
this.vy = vy;
this.text = text;
this.bgColor = bgColor;
}</p>
<p> draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.bgColor;
ctx.fill();
ctx.strokeStyle = 'rgba(0, 100, 200, 0.9)';
ctx.stroke();</p>
<p> // Draw text
ctx.font = 'bold 20px Arial';
ctx.fillStyle = '#000';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(this.text, this.x, this.y);
}</p>
<p> update() {
this.vy += gravity;
this.vx *= friction;
this.vy *= friction;
this.x += this.vx;
this.y += this.vy;</p>
<p> if (this.x + this.radius > canvasWidth) {
this.x = canvasWidth - this.radius;
this.vx *= -0.8;
}
if (this.x - this.radius < 0) {
this.x = this.radius;
this.vx *= -0.8;
}
if (this.y + this.radius > canvasHeight - boxHeight) {
this.y = canvasHeight - boxHeight - this.radius;
this.vy *= -0.8;
}</p>
<p> for (const other of circles) {
if (other !== this) {
const dx = this.x - other.x;
const dy = this.y - other.y;
const distance = Math.sqrt(dx * dx + dy * dy);
const minDistance = this.radius + other.radius;</p>
<p> if (distance < minDistance) {
const angle = Math.atan2(dy, dx);
const overlap = minDistance - distance;</p>
<p> // Separate the circles
this.x += Math.cos(angle) * (overlap / 2);
this.y += Math.sin(angle) * (overlap / 2);
other.x -= Math.cos(angle) * (overlap / 2);
other.y -= Math.sin(angle) * (overlap / 2);</p>
<p> // Simple collision response
const normalX = dx / distance;
const normalY = dy / distance;
const relativeVelocityX = this.vx - other.vx;
const relativeVelocityY = this.vy - other.vy;
const dotProduct = (relativeVelocityX * normalX) + (relativeVelocityY * normalY);</p>
<p> if (dotProduct > 0) {
const coefficientOfRestitution = 0.8; // Bounciness factor
const massSum = this.radius + other.radius;
const impulse = (2 * dotProduct) / massSum;</p>
<p> this.vx -= impulse * other.radius * normalX;
this.vy -= impulse * other.radius * normalY;
other.vx += impulse * this.radius * normalX;
other.vy += impulse * this.radius * normalY;
}
}
}
}
}
}</p>
<p> function generateRandomCircle(index) {
const radius = Math.random() * (maxRadius - minRadius) + minRadius;
const x = Math.random() * (canvasWidth - radius * 2) + radius;
const y = Math.random() * -500 - radius;
const vx = (Math.random() - 0.5) * 2;
const vy = (Math.random() - 0.5) * 2;
const text = Circlestexts[index];
const bgColor = Circlesbg[index];
return new Circle(x, y, radius, vx, vy, text, bgColor);
}</p>
<p> function createCircles() {
for (let i = 0; i < numCircles; i++) {
circles.push(generateRandomCircle(i));
}
}</p>
<p> function drawBox() {
ctx.fillStyle = 'rgba(100, 100, 100, 0.5)';
ctx.fillRect(0, canvasHeight - boxHeight, canvasWidth, boxHeight);
}</p>
<p> function animate() {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
drawBox();
for (const circle of circles) {
circle.update();
circle.draw();
}
requestAnimationFrame(animate);
}</p>
<p> createCircles();
animate();
</script>
</body>
</html></p>
<p>
이후엔 직접 한번 코드를 파보세요..
답변에 대한 댓글 1개
댓글을 작성하려면 로그인이 필요합니다.
답변에 대한 댓글 1개
댓글을 작성하려면 로그인이 필요합니다.
js 로는 어렵습니다..
아예 불가능한건 아닌데..
물리엔진 구현에는 한계가 있어서요...
떨어져야 하는 위치가 정해져 있다면 js+css 만으로도 가능해보이고
수박게임 처럼 위치가 불규칙적이라면 단순 js 만으로는 불가합니다.
답변에 대한 댓글 1개
참고래퍼런스입니다 연령별모임 섹션 쪽인데 js로만 어려울까요 ??
댓글을 작성하려면 로그인이 필요합니다.
아래의 코드 한번 참고를 해보시겠어요..
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Falling Animation</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
margin: 0;
overflow: hidden;
}
.container {
position: relative;
width: 300px;
height: 400px;
border: 2px solid #ccc;
border-radius: 10px;
overflow: hidden;
background-color: white;
}
.shape {
position: absolute;
width: 50px;
height: 50px;
background-color: red;
}
.shape.square {
border-radius: 0;
background-color: blue;
}
.shape.rectangle {
width: 30px;
height: 60px;
border-radius: 10px;
background-color: green;
}
.shape.triangle {
width: 0;
height: 0;
border-left: 25px solid transparent;
border-right: 25px solid transparent;
border-bottom: 50px solid yellow;
background-color: transparent;
}
</style>
</head>
<body>
<div class="container">
<div class="shape"></div>
<div class="shape square"></div>
<div class="shape rectangle"></div>
<div class="shape triangle"></div>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
const shapes = document.querySelectorAll('.shape');
const containerHeight = document.querySelector('.container').offsetHeight;
shapes.forEach((shape, index) => {
let delay = index * 0.5; // 각 도형마다 0.5초 간격으로 떨어지게 설정
shape.style.top = `-50px`; // 초기 위치 위로 설정
shape.style.left = `${Math.random() * 250}px`; // 무작위 위치 설정
// 애니메이션 시작
setTimeout(() => {
shape.style.transition = `top 2s ease-in-out`;
shape.style.top = `${containerHeight - shape.offsetHeight}px`; // 바닥까지 떨어지게 설정
}, delay * 1000);
});
});
</script>
</body>
</html>
답변에 대한 댓글 1개
댓글을 작성하려면 로그인이 필요합니다.
답변을 작성하려면 로그인이 필요합니다.
로그인