Stack/JavaScript

[JS] Wave

7ingout 2022. 6. 20. 10:42

 

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            outline: 0;
        }
        html {
            width: 100%;
            height: 100%;
        }
        body {
            width: 100%;
            height: 100%;
            background-color: #161e38;
        }
        canvas {
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body>
    <script type ="module" src="js/main.js"></script>
</body>
</html>

 

main.js

import { WaveGroup } from './wavegroup.js' 
class App {
    constructor() {
        // 캔버스 생성하기
        this.canvas = document.createElement('canvas');
        this.ctx = this.canvas.getContext('2d');
        document.body.appendChild(this.canvas);
        
        this.WaveGroup = new WaveGroup();
        window.addEventListener('resize', this.resize.bind(this), false);
        this.resize();

        window.requestAnimationFrame(this.animate.bind(this));
    }
    resize() {
        this.stageWidth = document.body.clientWidth;
        this.stageHeight = document.body.clientHeight;
        this.canvas.width = this.stageWidth * 2;
        this.canvas.height = this.stageHeight * 2;
        this.ctx.scale(2, 2);
        this.WaveGroup.resize(this.stageWidth, this.stageHeight);
    }
    animate(t) {
        this.ctx.clearRect(0, 0, this.stageWidth, this.stageHeight);
        this.WaveGroup.draw(this.ctx);
        window.requestAnimationFrame(this.animate.bind(this));
    }

}
window.onload = () => {
    new App();
}

 

point.js

export class Point {
    constructor(index, x, y) {
        this.x = x;
        this.y = y;
        this.fixedY = y;
        this.speed = 0.01;
        this.cur = index;
        this.max = Math.random() * 100 + 150;
    }
    update() {
        this.cur += this.speed;
        this.y = this.fixedY + (Math.sin(this.cur) * this.max);
    }
}

 

wave.js

import { Point } from "./point.js";

export class Wave {
    constructor(index, totalPoints, color) {
        this.index = index;
        this.totalPoints = totalPoints;
        this.color = color;
        this.points = [];
    }
    resize(stageWidth, stageHeight) {
        this.stageWidth = stageWidth;
        this.stageHeight = stageHeight;

        this.centerX = stageWidth / 2;
        this.centerY = stageHeight / 2;

        // 포인트 생성간격
        this.pointGap = this.stageWidth / (this.totalPoints - 1);

        this.init();
    }
    init() {
        // 포인트 배열을 생성
        this.points = [];
        for (let i =0; i<this.totalPoints; i ++) {
            const point = new Point (
                this.index +i,
                this.pointGap * i,
                this.centerY
            );
            // 배열에 순서대로 포인트 객체를 넣음
            this.points[i] = point;
        }
        // this.point = new Point(
        //     this.centerX,
        //     this.centerY,
        // )
    }
    draw(ctx) {
        ctx.beginPath();
        // ctx.fillStyle = '#ff0000';
        ctx.fillStyle = this.color;

        // this.point.update();
        // ctx.arc(this.point.x, this.point.y, 30, 0, Math.PI * 2);
        // ctx.fill();

        let prevX = this.points[0].x;
        let prevY = this.points[0].y;

        ctx.moveTo(prevX, prevY);
        // 첫번째와 마지막 점은 그위치에 두고 나머지만 업데이트
        for(let i =1; i<this.totalPoints; i++) {
            if(i < this.totalPoints -1) {
                this.points[i].update();
            }
            const cx = (prevX + this.points[i].x) / 2;
            const cy = (prevY + this.points[i].y) / 2;

            // 곡선으로 변경
            ctx.quadraticCurveTo(prevX, prevY, cx, cy);

            // ctx.lineTo(cx, cy);
            prevX = this.points[i].x;
            prevY = this.points[i].y;
        }
        ctx.lineTo(prevX, prevY);
        ctx.lineTo(this.stageWidth, this.stageHeight);
        ctx.lineTo(this.points[0].x, this.stageHeight);
        ctx.fill();
        ctx.closePath();
    }
}

 

waveGroup.js

import {Wave} from './wave.js';
export class WaveGroup {
    constructor() {
        this.totalWaves = 3;
        this.totalPoints = 6;

        this.color = ['rgba(0, 199, 235, 0.4)', 'rgba(0, 146, 199, 0.4)', 'rgba(0,87, 158, 0.4)'];
        this.waves = [];

        for(let i=0; i<this.totalWaves; i++) {
            const wave = new Wave(
                i,
                this.totalPoints,
                this.color[i],
            );
            this.waves[i] = wave;
        }
    }

    resize(stageWidth, stageHeight) {
        for(let i = 0; i<this.totalWaves; i++) {
            const wave = this.waves[i];
            wave.resize(stageWidth, stageHeight);
        }
    }

    draw(ctx) {
        for(let i=0; i<this.totalWaves; i ++) {
            const wave = this.waves[i];
            wave.draw(ctx);
        }
    }
}