用canvas绘制流星夜空

栏目: Html5 · 发布时间: 6年前

内容简介:流星是一种唯美的天文现象,我一度想用所学知识将它绘制,最近阅读MDN上的canvas教程得到启发,用一个canvas的长尾效果绘制流星……我们知道,canvas动画实现依赖于画布的重绘,通过不停的清空画布,绘制画布就能实现基本的动画效果。一般使用clearRect方法清除指定矩形区域,来实现重绘。长尾效果是使用透明的填充色代替clearRect方法来实现的。吐槽:由于录屏软件fps跟不上canvas所以这个gif图有点卡顿

流星是一种唯美的天文现象,我一度想用所学知识将它绘制,最近阅读MDN上的canvas教程得到启发,用一个canvas的长尾效果绘制流星……

用canvas绘制流星夜空

什么是长尾效果?

我们知道,canvas动画实现依赖于画布的重绘,通过不停的清空画布,绘制画布就能实现基本的动画效果。一般使用clearRect方法清除指定矩形区域,来实现重绘。长尾效果是使用透明的填充色代替clearRect方法来实现的。

使用clearRect

吐槽:由于录屏软件fps跟不上canvas所以这个gif图有点卡顿

用canvas绘制流星夜空

使用fillRect

1.透明度为1

用canvas绘制流星夜空

可以看出透明度为1时,效果与清除效果一致,我们可以理解为在画布上又盖上了一画布 ,遮住了之前所画的内容所以和清除效果是一样的。

2.透明度为0

用canvas绘制流星夜空

透明度为0的效果,则等价于没有清除画布的效果,此时运动的球体像一只尾巴不断变长的蛇,可以以此猜想,将透明度设为0~1之间,就能调整尾巴的长度,达到一个带尾巴的运动模糊效果。

3.长尾效果

用canvas绘制流星夜空

因为不断盖上透明的画布,所以从绘制点到出发点就产生了一条颜色不断变浅的路径,给人视觉效果就是一个动态模糊。

流星

可以将流星解构为一个圆形和长尾效果:

肉眼效果:

用canvas绘制流星夜空

实际效果:

用canvas绘制流星夜空

封装页面形状

使用面向对象编程完成canvas绘制

月亮类

class Moon {
    constructor(x, y, ctx, r = 25) {
        this.x = x;
        this.y = y;
        this.ctx = ctx;
        this.r = r;
    }
    draw() {
        this.ctx.fillStyle = 'rgba(255,255,255,0.6)';
        this.ctx.shadowBlur = this.r + 5; //光晕半径
        this.ctx.shadowColor = "#fff"; // 光晕颜色
        this.ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
        this.ctx.fill();
    }
}
复制代码

因为月亮是静止在页面上的,所以只有一个draw方法,月亮光晕的实现是把阴影和填充设为同一颜色,然后让阴影透明度大于填充透明度,就形成一个外发光的效果。

星星类

class Star extends Moon {
    constructor(x, y, ctx, r) {
        super(x, y, ctx, r);
    }
    draw() {
        this.ctx.fillStyle = 'rgba(255,255,255,0.8)';
        this.ctx.beginPath();
        this.ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
        this.ctx.closePath();
        this.ctx.fill();
    }
    move() {
        this.x += 0.08;
        if (this.x > meteorCanvas.width) {
            this.x = 0;
        }
        this.draw();
    }
}
复制代码

星星与月亮的唯一区别是可以移动,所以用星星类去继承月亮类,实现面向对象的继承与多态。

用星星缓慢的向右移动可以模拟地球自转带来的效果。

流星类

class Meteor extends Star {
    constructor(x, y, ctx, r,angle) {
        super(x, y, ctx, r);
        this.angle = angle;
    }
    draw() {
        this.ctx.fillStyle = '#ffffff';
        this.ctx.rotate(this.angle);
        this.ctx.translate(100, -meteorCanvas.height / 1.5);
        this.ctx.beginPath();
        this.ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
        this.ctx.closePath();
        this.ctx.fill();
        this.ctx.translate(-100, meteorCanvas.height / 1.5);
        this.ctx.rotate(-this.angle);
    }
    move() {
        this.x += 4;
        this.y += 1;
        if (this.x > meteorCanvas.width) {
            this.x = Math.random() * 5
            this.y = -2 * meteorCanvas.height + Math.random() * meteorCanvas.height * 3;
        }
        this.draw();
    }
}
复制代码

同理用流星类去继承星星类。

注意的是,流星类与星星类运动的不同之处是流星划过天空有一个夹角,所以在绘制时将画布旋转了角度之后,需要回归原位。

为了让流星出现的位置不会太密集,我将流星在y轴出现的位置设置在-2倍画布高度到1倍画布高度之间,并在draw方法中将画布往上挪了画布高度的2/3(同理要将画布归位)。

绘制canvas

流星需要使用长尾效果渲染,星星需要clearRect重绘,月亮就只需要绘制一次。为了三种形状互不干扰,我分别使用了不同画布去渲染它们。

优点:互不干扰,绘制逻辑清晰,优化渲染。

源码

const meteorCanvas = document.getElementById('meteor');
        const starCanvas = document.getElementById('star');
        const moonCanvas = document.getElementById('moon');
        const meteors = [], stars = [];

        meteorCanvas.width = document.body.clientWidth;
        meteorCanvas.height = document.body.clientHeight;
        starCanvas.width = document.body.clientWidth;
        starCanvas.height = document.body.clientHeight / 3;
        moonCanvas.width = document.body.clientWidth;
        moonCanvas.height = document.body.clientHeight / 3;
        const meteorCtx = meteorCanvas.getContext('2d');
        const starCtx = starCanvas.getContext('2d');
        const moonCtx = moonCanvas.getContext('2d');

        init();
        animate();

        function init() {
            for (var i = 0; i < 4; i++) {
                meteors[i] = new Meteor(Math.random() * meteorCanvas.width,
                    -2 * meteorCanvas.height + Math.random() * meteorCanvas.height * 3,
                    meteorCtx, Math.floor(Math.random() * 2) + 1.5, Math.PI / 7);
                meteors[i].draw();
            }
            for (var i = 0; i < 60; i++) {
                stars[i] = new Star(Math.random() * starCanvas.width, Math.random() * starCanvas.height,
                    starCtx, Math.random());
                stars[i].draw();
            }
            moon = new Moon(moonCanvas.width - 50, 50, moonCtx)
            moon.draw();
        }
        function animate() {
            starCtx.clearRect(0, 0, starCanvas.width, starCanvas.height);
            meteorCtx.fillStyle = `rgba(0, 0, 0, 0.1)`;
            meteorCtx.fillRect(0, 0, meteorCanvas.width, meteorCanvas.height);
            for (let meteor of meteors)
                meteor.move();
            for (let star of stars)
                star.move();
            requestAnimationFrame(animate);
        }
        function recover() {
            for (let meteor of meteors)
                meteor = null;
            for (let star of stars)
                star = null;
            moon = null;
        }
        window.onresize = function () {
            meteorCanvas.width = document.body.clientWidth;
            meteorCanvas.height = document.body.clientHeight;
            starCanvas.width = document.body.clientWidth;
            starCanvas.height = document.body.clientHeight / 3;
            moonCanvas.width = document.body.clientWidth;
            moonCanvas.height = document.body.clientHeight / 3;
            recover();
            init();
        }
复制代码

结语

陪你去看流星雨落在这地球上

让你的泪落在我肩膀

要你相信我的爱只肯为你勇敢……

文章随着《流星雨》的歌声,也走向了尾声。人生如流星划过,转瞬即逝,然而,流星易逝,真情永恒……


以上所述就是小编给大家介绍的《用canvas绘制流星夜空》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Smashing Book

The Smashing Book

Jacob Gube、Dmitry Fadeev、Chris Spooner、Darius A Monsef IV、Alessandro Cattaneo、Steven Snell、David Leggett、Andrew Maier、Kayla Knight、Yves Peters、René Schmidt、Smashing Magazine editorial team、Vitaly Friedman、Sven Lennartz / 2009 / $ 29.90 / € 23.90

The Smashing Book is a printed book about best practices in modern Web design. The book shares technical tips and best practices on coding, usability and optimization and explores how to create succes......一起来看看 《The Smashing Book》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具