HTML + JQuery + CSS 实现动态变色雪花特效

在这里插入图片描述

在这里插入图片描述

snow.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>snow</title>

    <script type="text/javascript" src="js/jquery-1.12.4.min.js"></script>

    <style>
        html,body {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
        .container{
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }</style>
</head>

<body>
<div id="jsi-snow-container" class="container"></div>

<script>
    var RENDERER = {
        SNOW_COUNT: {INIT : 100, DELTA : 1},
        BACKGROUND_COLOR : 'hsl(%h, 50%, %l%)',
        INIT_HUE : 180,
        DELTA_HUE : 0.1,

        init : function(){
            this.setParameters();
            this.reconstructMethod();
            this.createSnow(this.SNOW_COUNT.INIT * this.countRate, true);
            this.render();
        },
        setParameters : function(){
            this.$window = $(window);

            this.$container = $('#jsi-snow-container');
            this.width = this.$container.width();
            this.height = this.$container.height();
            this.center = {x : this.width / 2, y : this.height / 2};
            this.countRate =  this.width * this.height / 500 / 500;
            this.canvas = $('<canvas />').attr({width : this.width, height : this.height}).appendTo(this.$container).get(0);
            this.context = this.canvas.getContext('2d');

            this.radius = Math.sqrt(this.center.x * this.center.x + this.center.y * this.center.y);
            this.hue = this.INIT_HUE;
            this.snows = [];
        },
        reconstructMethod : function(){
            this.render = this.render.bind(this);
        },
        createSnow : function(count, toRandomize){
            for(var i = 0; i < count; i++){
                this.snows.push(new SNOW(this.width, this.height, this.center, toRandomize));
            }
        },
        render : function(){
            requestAnimationFrame(this.render);

            var gradient = this.context.createRadialGradient(this.center.x, this.center.y, 0, this.center.x, this.center.y, this.radius),
                backgroundColor = this.BACKGROUND_COLOR.replace('%h', this.hue);

            gradient.addColorStop(0, backgroundColor.replace('%l', 30));
            gradient.addColorStop(0.2, backgroundColor.replace('%l', 20));
            gradient.addColorStop(1, backgroundColor.replace('%l', 5));

            this.context.fillStyle = gradient;
            this.context.fillRect(0, 0, this.width, this.height);

            for(var i = this.snows.length - 1; i >= 0; i--){
                if(!this.snows[i].render(this.context)){
                    this.snows.splice(i, 1);
                }
            }
            this.hue += this.DELTA_HUE;
            this.hue %= 360;

            this.createSnow(this.SNOW_COUNT.DELTA, false);
        }
    };
    var SNOW = function(width, height, center, toRandomize){
        this.width = width;
        this.height = height;
        this.center = center;
        this.init(toRandomize);
    };
    SNOW.prototype = {
        RADIUS : 20,
        OFFSET : 4,
        INIT_POSITION_MARGIN : 20,
        COLOR : 'rgba(255, 255, 255, 0.8)',
        TOP_RADIUS : {MIN : 1, MAX : 3},
        SCALE : {INIT : 0.04, DELTA : 0.01},
        DELTA_ROTATE : {MIN : -Math.PI / 180 / 2, MAX : Math.PI / 180 / 2},
        THRESHOLD_TRANSPARENCY : 0.7,
        VELOCITY : {MIN : -1, MAX : 1},
        LINE_WIDTH : 2,
        BLUR : 10,
        init : function(toRandomize){
            this.setParameters(toRandomize);
            this.createSnow();
        },
        setParameters : function(toRandomize){
            if(!this.canvas){
                this.radius = this.RADIUS + this.TOP_RADIUS.MAX * 2 + this.LINE_WIDTH;
                this.length = this.radius * 2;
                this.canvas = $('<canvas />').attr({width : this.length, height : this.length}).get(0);
                this.context = this.canvas.getContext('2d');
            }
            this.topRadius = this.getRandomValue(this.TOP_RADIUS);

            var theta = Math.PI * 2 * Math.random();

            this.x = this.center.x + this.INIT_POSITION_MARGIN * Math.cos(theta);
            this.y = this.center.y + this.INIT_POSITION_MARGIN * Math.sin(theta);
            this.vx = this.getRandomValue(this.VELOCITY);
            this.vy = this.getRandomValue(this.VELOCITY);

            this.deltaRotate = this.getRandomValue(this.DELTA_ROTATE);
            this.scale = this.SCALE.INIT;
            this.deltaScale = 1 + this.SCALE.DELTA * 500 / Math.max(this.width, this.height);
            this.rotate = 0;

            if(toRandomize){
                for(var i = 0, count = Math.random() * 1000; i < count; i++){
                    this.x += this.vx;
                    this.y += this.vy;
                    this.scale *= this.deltaScale;
                    this.rotate += this.deltaRotate;
                }
            }
        },
        getRandomValue : function(range){
            return range.MIN + (range.MAX - range.MIN) * Math.random();
        },
        createSnow : function(){
            this.context.clearRect(0, 0, this.length, this.length);

            this.context.save();
            this.context.beginPath();
            this.context.translate(this.radius, this.radius);
            this.context.strokeStyle = this.COLOR;
            this.context.lineWidth = this.LINE_WIDTH;
            this.context.shadowColor = this.COLOR;
            this.context.shadowBlur = this.BLUR;

            var angle60 = Math.PI / 180 * 60,
                sin60 = Math.sin(angle60),
                cos60 = Math.cos(angle60),
                threshold = Math.random() * this.RADIUS / this.OFFSET | 0,
                rate = 0.5 + Math.random() * 0.5,
                offsetY = this.OFFSET * Math.random() * 2,
                offsetCount = this.RADIUS / this.OFFSET;

            for(var i = 0; i < 6; i++){
                this.context.save();
                this.context.rotate(angle60 * i);

                for(var j = 0; j <= threshold; j++){
                    var y = -this.OFFSET * j;

                    this.context.moveTo(0, y);
                    this.context.lineTo(y * sin60, y * cos60);
                }
                for(var j = threshold; j < offsetCount; j++){
                    var y = -this.OFFSET * j,
                        x = j * (offsetCount - j + 1) * rate;

                    this.context.moveTo(x, y - offsetY);
                    this.context.lineTo(0, y);
                    this.context.lineTo(-x, y - offsetY);
                }
                this.context.moveTo(0, 0);
                this.context.lineTo(0, -this.RADIUS);
                this.context.arc(0, -this.RADIUS - this.topRadius, this.topRadius, Math.PI / 2, Math.PI * 2.5, false);
                this.context.restore();
            }
            this.context.stroke();
            this.context.restore();
        },
        render : function(context){
            context.save();

            if(this.scale > this.THRESHOLD_TRANSPARENCY){
                context.globalAlpha = Math.max(0, (1 - this.scale) / (1 - this.THRESHOLD_TRANSPARENCY));

                if(this.scale > 1 || this.x < -this.radius || this.x > this.width + this.radius || this.y < -this.radius || this.y > this.height + this.radius){
                    context.restore();
                    return false;
                }
            }
            context.translate(this.x, this.y);
            context.rotate(this.rotate);
            context.scale(this.scale, this.scale);
            context.drawImage(this.canvas, -this.radius, -this.radius);
            context.restore();

            this.x += this.vx;
            this.y += this.vy;
            this.scale *= this.deltaScale;
            this.rotate += this.deltaRotate;
            return true;
        }
    };
    $(function(){
        RENDERER.init();
    });</script>
</body>
</html>

jquery-1.12.4.min.js
新建js文件,复制下面网址中内容

https://code.jquery.com/jquery-1.12.4.min.js
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值