canvas动画, 三阶贝塞尔曲线, 波浪效果

再此不做学习介绍,没有什么复杂的
*.7z 格式全代码下载

index.html

仅引用和基础样式

<Doctument>
    <head>
        <meta charset="utf-8">
        <title>Home</title>
    </head>
    <body>
        <canvas id="canvas"></canvas>
        <script type="module" src="./app.js"></script>
    </body>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
        html,
        body {
            width: 100%;
            height: 100vh;
            overflow: hidden;
        }
        #canvas {
            width: 100%;
            height: 100%;
        }
    </style>
</Doctument>

app.js

动画总控制方法 可公用

/*app.js*/
import WaveSea from "./WaveSea.js";

class Application {
    constructor() {
        this.canvas = null;       // 画布
        this.ctx = null;          // 环境
        this.w = 0;               // 画布宽
        this.h = 0;               // 画布高
        this.animations = [];
        
        this.init();
    }
    init() {
        // 初始化
        this.canvas = document.getElementById("canvas");
        this.ctx = this.canvas.getContext("2d");
        window.addEventListener("resize", this.reset.bind(this));
        this.reset();
        this.step();
        this.render();
    }
    reset() {
        // 屏幕改变
        this.w = this.canvas.width = this.ctx.width = window.innerWidth;
        this.h = this.canvas.height = this.ctx.height = window.innerHeight;
        this.render();
    }
    render() {
        const { w, h, ctx } = this;
        this.animations = [
            new WaveSea({ screenX: w, screenY: h }).render(ctx),
            new WaveSea({ screenX: w, screenY: h }).render(ctx),
            new WaveSea({ screenX: w, screenY: h }).render(ctx),
        ];
    }
    step() {
        const { w, h, ctx } = this;
        requestAnimationFrame(this.step.bind(this));
        ctx.clearRect(0, 0, w, h);
        this.animations.map(animation => {
            animation.update();
        })
    }
}

window.onload = new Application();

WaveSea.js

/*WaveSea.js*/
class WaveSea {
    constructor(options) {
        // 场景宽高
        this.screenX = options.screenX;
        this.screenY = options.screenY;
        // 每次移动的距离 随机数字
        this.speed = (Math.random() + 2) * Math.random();
        // 活动坐标 (活动起始坐标)
        this.x = 0 - this.speed * 20;
        this.y = 1 / 3 * this.screenY;
        // y轴的波动值 (y轴的波动值越大, 波动越大)
        this.wave = 2 / 5 * this.y;
        // x循环的长度 (x循环的长度越大, 波动距离越长)
        this.size = 400;

        // 外部设置值
        Object.assign(this, options);
    }
    render(ctx) {
        this.ctx = ctx;

        this.drawWave();
        return this;
    }
    drawWave() {
        const { ctx, screenX, screenY } = this;

        ctx.beginPath();
        this.drawOneWave(this.x);
        ctx.lineTo(screenX, screenY);
        ctx.lineTo(0, screenY);
        ctx.lineTo(this.x, this.y);

        ctx.fillStyle = "rgba(16,150,250,0.5)";
        ctx.fill();
    }
    drawOneWave(x) {
        const { ctx, y, size, wave, screenX } = this;
        let set = [
            [x, y],
            [x + (1 / 3 * size), y - wave],
            [x + (2 / 3 * size), y + wave],
            [x + size, y],
        ]
        ctx.moveTo(set[0][0], set[0][1]);
        ctx.bezierCurveTo(set[1][0], set[1][1], set[2][0], set[2][1], set[3][0], set[3][1]);

        if (x + size < screenX)
            this.drawOneWave(x + size);
        else
            ctx.save();
    }
    update() {
        this.x -= this.speed;
        this.drawWave();
    }
}

export default WaveSea;

备注

  1. 下载了wave-ball 加载进度球
  2. canvas动画即擦除重画,幻灯片,理解
  3. 所以需要的仅仅是知道怎么画静态
  4. 然后外部控制画图的移动即可
posted @ 2022-01-24 15:48  qoon  阅读(312)  评论(0)    收藏  举报