테스트 사이트 - 개발 중인 베타 버전입니다

아래로 떨어지면서 쌓이는 애니메이션 도와주세요ㅠㅠ!!!! 채택완료

나쨘도링 1년 전 조회 14,332

http://sir.kr/data/editor/2408/3673009239_1722487078.1125.png" width="402" />

 

아래로 떨어지면서 쌓이는 애니메이션을 구현하고 싶은데 js 만으로 구현이 될까요 ????ㅠㅠ 

전부 리엑트로 구현한 것만 나와서 ㅠㅠ.... 오픈코드 아시는분 부탁드립니다 ,,!!! 

댓글을 작성하려면 로그인이 필요합니다.

답변 5개

채택된 답변
+20 포인트

단순 위에서 아래로 중력에 의한 오브젝트 정렬이라면

 

</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개

나쨘도링
1년 전
구글신도 코드가 잘 안나오네요 .... 구글신보다 애드프로님이 더 신입니다 ..! 와 최고에요 ㅠㅠ 감사합니다 ㅠㅠ 혹시 안에 공들 색상이나 텍스트 추가도 할 수 있는 걸까요 ????
애드프로
1년 전
GPT가 신이죠 ㅎㅎ
나쨘도링
1년 전
아니면 공들대신 이미지 삽입도 가능한걸까요 ???? 애드프로님이 구글보다 대단하심다 ...! ㅠㅠ

댓글을 작성하려면 로그인이 필요합니다.

</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년 전
정말정말 감사합니다!!!!! 쪽지 한번 만 봐주세요!!!

댓글을 작성하려면 로그인이 필요합니다.

1년 전

혹시 원하시는 형태로 정확히 동작하는 샘플 주소나 다른 코드 경로 찍어주실 수 있으세요~

로그인 후 평가할 수 있습니다

답변에 대한 댓글 1개

나쨘도링
1년 전
https://campaign.naver.com/band-10th-anniversary/ 여기입니다! 공이 떨어지는 부분이요! ㅠㅠ

댓글을 작성하려면 로그인이 필요합니다.

js 로는 어렵습니다..

아예 불가능한건 아닌데..

물리엔진 구현에는 한계가 있어서요...

 

떨어져야 하는 위치가 정해져 있다면 js+css 만으로도 가능해보이고

수박게임 처럼 위치가 불규칙적이라면 단순 js 만으로는 불가합니다.

로그인 후 평가할 수 있습니다

답변에 대한 댓글 1개

나쨘도링
1년 전
https://campaign.naver.com/band-10th-anniversary/

참고래퍼런스입니다 연령별모임 섹션 쪽인데 js로만 어려울까요 ??

댓글을 작성하려면 로그인이 필요합니다.

1년 전

아래의 코드 한번 참고를 해보시겠어요..

 

 

<!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개

나쨘도링
1년 전
노란색 세모가 그 밑에 도형들 위로 쌓이게는 못할까요 ?!!? ㅠㅠ 도형들이 쌓이게끔 ...

댓글을 작성하려면 로그인이 필요합니다.

답변을 작성하려면 로그인이 필요합니다.

로그인