• 使用Canvas实现下雪功能


    示例代码:

    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
        <meta charset="utf-8" />
        <style>
            body {
                background:#333;
            }
        </style>
    </head>
    <body>
        <button id="start-snowFall">开始</button>
        <button id="stop-snowFall">停止</button>
        <button id="pause-snowFall">暂停</button>
        <button id="resume-snowFall">回复</button>
        <script>
            window.onload = function () {
                //绑定事件
                var snow = new snowFall({ maxFlake: 200 });
                var start = document.getElementById('start-snowFall'),
                    stop = document.getElementById('stop-snowFall'),
                    pause = document.getElementById('pause-snowFall'),
                    resume = document.getElementById('resume-snowFall');
                //开始
                start.onclick = function () {
                    snow.start();
                }
                //停止
                stop.onclick = function () {
                    snow.stop();
                }
                //暂停
                pause.onclick = function () {
                    snow.pause();
                }
                //回复
                resume.onclick = function () {
                    snow.resume();
                }
            }
            //控制对象封装
            function snowFall(snow) {
                //可配置属性
                snow = snow || {};
                this.maxFlake = snow.maxFlake || 200; //最多骗术
                this.flakeSize = snow.flakeSize || 10;// 雪花形状
                this.fallSpeed = snow.fallSpeed || 2;//坠落速度
                this.status = 0; //0-初始化、1-开始下雪 、2--停止下雪 、3--暂停下雪、4--继续下雨
            }
            //兼容写法
            requestAnimationFrame = window.requestAnimationFrame ||
                window.mozRequestAnimationFrame ||
                window.webkitRequestAnimationFrame ||
                window.msRequestAnimationFrame ||
                window.oRequestAnimationFrame ||
                function (callback) { setTimeout(callback, 1000 / 60) };
            cancelAnimationFrame = window.cancelAnimationFrame ||
                window.mozCancelAnimationFrame ||
                window.webkitCancelAnimationFrame ||
                window.msCancelAnimationFrame ||
                window.oCancelAnimationFrame;
    
            //开始下雪
            snowFall.prototype.start = function () {
                if (this.status == 1 || this.status == 4)
                    return false;
                this.status = 1;
                //创建画布
                snowCanvas.apply(this);
                //创建雪花形状
                createFlakes.apply(this);
                //画学
                drawSnow.apply(this);
            }
            //停止下雪
            snowFall.prototype.stop = function () {
                if (this.status == 2 || this.status == 0 || !this.canvas) {
                    return false;
                }
                //定制动画循环
                this.pause();
                this.status = 2;
                //删除画布
                this.canvas.parentNode.removeChild(this.canvas);
                this.canvas = null;
            };
            //暂停下雪
            snowFall.prototype.pause = function () {
                if (this.status == 3) {
                    return false;
                }
                this.status = 3;
                cancelAnimationFrame(this.loop);
            }
            //继续下雪
            snowFall.prototype.resume = function () {
                if (this.status == 3 && this.canvas) {
                    this.status = 4;
                    //动画的计时控制
                    this.loop = requestAnimationFrame(function () {
                        drawSnow.apply(that);
                    });
                }
            }
            //创建画布
            function snowCanvas() {
                //添加Dom节点
                var snowcanvas = document.createElement('canvas');
                snowcanvas.id = 'snowfall';
                snowcanvas.width = window.innerWidth;
                snowcanvas.height = window.innerHeight;
                snowcanvas.setAttribute('style', 'position:fixed;top:0;left:0;z-index:2999;pointer-events:none;');
                
                document.getElementsByTagName('body')[0].appendChild(snowcanvas);
                this.canvas = snowcanvas;
                this.ctx = snowcanvas.getContext('2d');
                //窗口大小改变处理
                window.onresize = function () {
                    snowcanvas.width = window.innerWidth;
                    snowcanvas.height = window.innerHeight;
                }
            }
            //创建雪花
            function createFlakes() {
                var maxFlake = this.maxFlake,
                    flakes = this.flakes = [],
                    canvas = this.canvas;
                for (var i = 0; i < maxFlake; i++) {
                    flakes.push(new flakeMove(canvas.width, canvas.height, this.flakeSize, this.fallSpeed));
                }
            }
            //雪运动对象
            function flakeMove(canvasWidth, canvasHeight, flakeSize, fallSpeed) {
                this.x = Math.floor(Math.random() * canvasWidth);   //x坐标
                this.y = Math.floor(Math.random() * canvasHeight);  //y坐标
                this.size = Math.random() * flakeSize + 2;          //形状
                this.masSize = flakeSize;                           //最大形状
                this.speed = Math.random() * 1 + fallSpeed;         //坠落速度
                this.fallSpeed = fallSpeed;                         //坠落速度
                this.velY = this.speed;                             //y方向速度
                this.velX = 0;                                      //x方向速度
                this.stepSize = Math.random() / 30;                 //步长 
                this.step = 0;                                      //步数
            }
            //重置当前雪花的位置
            flakeMove.prototype.update = function () {
                var x = this.x,
                    y = this.y;
                //左右摆动(余弦)
                this.velX *= 0.98;
                if (this.velY <= this.speed) {
                    this.velY = this.speed;
                }
                this.velX += Math.cos(this.step += 0.05) * this.stepSize;
    
                this.y += this.velY;
                this.x += this.velX;
                //飞出边界处理
                if (this.x >= canvas.width || this.x <= 0 || this.y >=canvas.height || this.y <= 0) {
                    this.reset(canvas.width,canvas.height);
                }
            }
            //飞出边界--放置最顶端继续坠落
            flakeMove.prototype.reset = function (width, height) {
                this.x = Math.floor(Math.random() * width);
                this.y = 0;
                this.size = Math.random() * this.masSize + 2;
                this.speed = Math.random() * 1 + this.fallSpeed;
                this.velY = this.speed;
                this.velX = 0;
            }
            //渲染雪花--随机形状
            flakeMove.prototype.render = function (ctx) {
                var snowFlake = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.size);
                snowFlake.addColorStop(0, 'rgba(255,255,255,0.9)');
                snowFlake.addColorStop(0.5, 'rgba(255,255,255,0.5)');
                snowFlake.addColorStop(1, 'rgba(255,255,255,0)');
                ctx.save();
                ctx.fillStyle = snowFlake;
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                ctx.fill();
                ctx.restore();
            }
            //滑雪
            function drawSnow() {
                var maxFlake = this.maxFlake,
                    flakes = this.flakes;
                ctx = this.ctx,
                canvas = this.canvas,
                that = this;
                //清空
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                for (var i = 0; i < maxFlake; i++) {
                    flakes[i].update();
                    flakes[i].render(ctx);
                }
                //一折一帧的画
                this.loop = requestAnimationFrame(function () {
                    drawSnow.apply(that);
                });
            }
        </script>
    </body>
    </html>

    显示结果:

    1.主要代码

    this.step = 0;
    this.stepSize = Math.random() / 30;
    this.velX += Math.cos(this.step += .05) * this.stepSize;
    this.x += this.velX;

    step从0开始,每一帧增加0.05,相当于上图的横轴(X坐标)随着时间向右走

    Math.cos(this.step += .05)则为上图对应的数轴(Y坐标),会随着step的增加,呈现1到-1的抛物线变换,正负值使得velX有左右方向

    stepSize为步长,因为一帧有几十毫秒,很快,所以这个值为小于1/30的一个随机数

    x为雪花的X坐标位置,就会在界面左右摆动

  • 相关阅读:
    守护线程与普通线程
    Java中实现多线程的两种方式之间的区别
    Python os.dup() 方法
    Python os.closerange() 方法
    Python os.close() 方法
    Python os.chroot() 方法
    Python os.chmod() 方法
    JavaScript——基本包装类型
    javascript——function类型(this关键字)
    常用的正则
  • 原文地址:https://www.cnblogs.com/tianma3798/p/5183223.html
Copyright © 2020-2023  润新知