怕你不信,100行极简原生html现实3D雪花飘飘动效

纯原生JS结合HTML5 Canvas实现逼真的大雪纷飞效果。
下雪
用到的snow_1.png是一张很小的雪花图片,通过如下js代码在canvas里面画出来,右键保存备用。

function drawPic() {
    canvas.width = 20;
    canvas.height = 20;
    var grd = context.createRadialGradient(10, 10, 1, 10, 10, 10);
    grd.addColorStop(0, 'white');
    grd.addColorStop(1, 'rgba(255,255,255,0)');
    context.fillStyle = grd;
    context.fillRect(0, 0, canvas.width, canvas.height);
}

背景图是在百度图片随便下载了一张雪地图片:
在这里插入图片描述

100行完整html代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>大雪纷飞</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <style>
        html,body{
            height: 100%;
            margin: 0;
            padding: 0;
        }
        body{
            background: url("images/bg.jpg") no-repeat center center;
            background-size: cover;
        }
    </style>
</head>
<body>
<canvas id="main"></canvas>
</body>
<script>
    window.onload = function(){
        var canvas = document.getElementById("main");
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        var context = canvas.getContext('2d');
        document.body.appendChild(canvas);

        var snowNum = 2000;
        var particles = [];
        var snowImg = new Image();
        snowImg.src = "images/snow_1.png";
        snowImg.onload = function() {
            init();
        }
        var groundStart = window.innerHeight*0.6;
        function Particle3D() {
            this.x = Math.random() * 2000 - 1000;
            this.y = Math.random() * 2000 - 1000;
            this.z = Math.random() * 1000 - 1000;
            this.vx = Math.random()*1-1;
            this.vy = Math.random()*1+1;
            this.vz = Math.random()*1-2;
            this.width = snowImg.width;
            this.height = snowImg.height;
            this.scale = (this.z + 1000)/2000;
            this.max = groundStart + window.innerHeight*this.scale;
            this.update = function() {
                this.x += this.vx;
                this.y += this.vy;
                this.z += this.vz;
                this.scale = (this.z + 1000)/2000;
                this.max = groundStart + window.innerHeight*this.scale;
            }
            this.draw = function(ctx) {
                var centerX= this.x+this.width/2;
                var centerY= this.y+this.height/2;
                var width = this.width*this.scale;
                var height = width;//this.height*this.scale;
                var x = centerX - width/2;
                var y = centerY - height/2;
                if(width>=1) {
                    ctx.drawImage(snowImg,x,y,width,height);
                }
            }
        }
        function init() {
            for(var i=0;i<snowNum;i++) {
                var dot = new Particle3D();
                particles.push(dot);
                dot.draw(context);
            }
            requestAnimationFrame(loop);
        }
        function loop() {
            context.clearRect(0,0,canvas.width,canvas.height);
            for (var i = 0; i < particles.length; i++) {
                var dot = particles[i];
                dot.update();
                with (dot) {
                    if (y >=dot.max) {
                        y -= 2000
                    }
                    if (x > 1000) {
                        x -= 2000
                    } else if (x < -1000) {
                        x += 2000
                    }
                    if (z < -1000) {
                        z += 1000
                    }
                }
                dot.draw(context);
            }
            requestAnimationFrame(loop);
        }
    };
</script>
</html>

1 需要注意的是,需要设定Canvas的大小,否则默宽高是300x150。不能简单地给canvas标签指定style="width:100%;height:100%",那样的话canvas会由300x150的尺寸强制拉伸到screenWidth*screenHeight
2 代码尽可能原始而简单,有几个地方代码可以优化,但效果已经实现了。另外雪花在飘下过程中近大远小的模拟也有其他更复杂的模型。
欢迎转载,欢迎copy,欢迎留言交流~~~

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值