JavaScript 朝着群星前进的动态背景

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf8">
        <meta http-equiv="X-UA-Compatible" content="IE-edge, chrome=1">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>朝着群星前进(Toward The Stars)</title>
        <style>
            body {
                overflow: hidden;
                background-color: #00113F;
            }
            #inputDiv {
                /* 要在canvas上显示控件,需要设置position:absolute,并将left和top置为0 */
                position: absolute;
                left: 0;
                top: -230px;
                margin: 5px;
                padding:10px;
                background-color: white;
                border-bottom-left-radius:10px;
                border-bottom-right-radius:10px;
                transition: top 1s;
            }
            #inputDiv:hover {
                top: 0px;
            }
            .configLine {
                border-bottom: 1px solid black;
                padding-top: 5px;
                padding-bottom: 5px;
            }
            #configTitle {
                text-align: center;
                padding-top: 5px;
            }
            #inputDiv table{
                border-bottom: 1px solid black;
            }
            #inputDiv input {
                margin-bottom: 10px;
                /* 要让input居中只要将它的边距全部去掉即可 */
                margin:0px; 
                padding:0px;
                /* 添加这句后按钮和文字才会对齐 */
                vertical-align:middle;
            }
            #inputDiv input[type=range] {
                margin-top: 5px;
                width: 170px;
            }
        </style>
    </head>
    <body>
        <canvas id="canvas">Your browser can not support canvas</canvas>
        <div id="inputDiv">
            <table>
                <tr class="configLine">
                    <td>Backgrond Color</td>
                    <td><input id="bgColor" type="color" value="#00113F"/></td>
                </tr>
                <tr class="configLine">
                    <td>Star Color</td>
                    <td><input id="starColor" type="color" value="#FBFFAF"/></td>
                </tr>
            </table>
            <div class="configLine">
                 Star Shape<br/>
                 <input id="starShapeSquare" type="radio" name="starShapes" value="square" checked/>square
                 <input id="starShapeCircle" type="radio" name="starShapes" value="circle"/>circle
            </div>
            <div class="configLine">
                 Animation Schemes<br/>
                 <input id="starAnimationScheme1" type="radio" name="starAnimationSchemes" value="scheme1" checked/>scheme1
                 <input id="starAnimationScheme2" type="radio" name="starAnimationSchemes" value="scheme2"/>scheme2
            </div>
            <div class="configLine">
                <div id="towardStepTip">Toward Step:10</div>
                <input id="towardStepRange" type="range" min="0" max="30" value="10"/>
            </div>
            <div id="configTitle">参数面板</div>
        </div>
        <script>
            var canvas = document.getElementById("canvas");
            var ctx = canvas.getContext("2d");

            var starSky;

            //星空
            var StarSky = function() {
                var doublePI = Math.PI * 2;
                var _this = this;

                //星星粒子颜色
                this.starColor = "#FBFFAF";
                //星星的类型(square、circle)
                this.starShape = "square";
                //动画方案(scheme1、scheme2)
                this.animationSchema = "scheme1";

                //星星个数是画布长加宽的某个比例
                var starCountRatio = 0.4;
                //星体缩放系数
                var starScaleRatio = 0.3;
                //星空深处直径与画布短边的比
                var depthSkySizeRatio = 0.5;
                //星空深度
                this.skyDepth = 400;
                //每帧朝前移动的步长
                this.towardStep = 10;

                //星空中心X坐标
                var cx;
                //星空中心Y坐标
                var cy;
                //星空深处的半径
                var skyDepthRadius;
                //星空深处的直径
                var skyDepthDiameter;

                //星星粒子个数
                var starCount;
                //星空粒子数组
                var stars;

                //判断点是否在画布中
                function isOutCanvas(x, y) {
                    return (x < 0 || y < 0 || x > canvas.width || y > canvas.height);
                }

                //星空粒子
                var StarParticle = function() {
                    //随机一个画布中心的偏移点
                    this.offsetX = -skyDepthRadius + skyDepthDiameter * Math.random();
                    this.offsetY = -skyDepthRadius + skyDepthDiameter * Math.random();
                    //深度随机为视口到最深处
                    this.depth = _this.skyDepth * Math.random();

                    this.update = function() {
                        //星体每次向视口前进一步
                        this.depth -= _this.towardStep;
                        if(this.depth < 0) {
                            this.depth += _this.skyDepth;
                        }
                        var scale = 1;
                        switch(_this.animationSchema) {
                            case "scheme1":
                                //设星空最深处的缩放比例是某个系数
                                scale = _this.skyDepth / this.depth * starScaleRatio;
                                //半径等于缩放比例
                                this.radius = scale;
                            break;
                            case "scheme2":
                                //设星空最深处的缩放比例是1
                                var scale = _this.skyDepth / this.depth;
                                //半径等于缩放比例乘以某个系数
                                this.radius = scale * starScaleRatio;
                            break;
                        }
                        this.x = cx + this.offsetX * scale;
                        this.y = cy + this.offsetY * scale;
                    }

                    this.render = function() {
                        //画布之外和半径太小的点就没必要绘制了
                        if(isOutCanvas(this.x, this.y) || this.radius < 0.1) {
                            return;
                        }
                        switch(_this.starShape) {
                            case "square":
                                ctx.strokeStyle = _this.starColor;
                                ctx.lineWidth = this.radius * 2;
                                ctx.beginPath();
                                ctx.moveTo(this.x - this.radius, this.y);
                                ctx.lineTo(this.x + this.radius, this.y);
                                ctx.stroke();
                            break;
                            case "circle":              
                                ctx.fillStyle = _this.starColor;
                                ctx.beginPath();
                                ctx.arc(this.x, this.y, this.radius, 0, doublePI);
                                ctx.fill();
                            break;
                        }
                    }
                }

                function update() {
                    for(var i=0; i<starCount; i++) {
                        stars[i].update();
                    }
                }

                function render() {
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    for(var i=0; i<starCount; i++) {
                        stars[i].render();
                    }
                }

                function loop() {
                    update();
                    render();
                    requestAnimationFrame(loop);
                }

                //初始化星空粒子
                this.initStar = function() {
                    cx = canvas.width / 2;
                    cy = canvas.height / 2;
                    starCount = Math.round((canvas.width + canvas.height) * starCountRatio);
                    skyDepthRadius = Math.min(cx, cy) * depthSkySizeRatio;
                    skyDepthDiameter = 2 * skyDepthRadius;
                    this.skyDepth = 2 * this.skyDepth;
                    stars = new Array(starCount);
                    for(var i=0; i<starCount; i++) {
                        stars[i] = new StarParticle();
                    }
                    loop();
                }

            }

            //当网页大小改变时触发
            function onResize() {
                canvas.width = document.body.clientWidth;
                canvas.height = window.innerHeight;
                starSky.initStar();
            }

            //当设置星星形状
            function onStarShapeChange() {
                starSky.starShape = event.target.value;
            }

            //当设置动画的方案
            function onStarAnimationSchemeClick() {
                starSky.animationSchema = event.target.value;
            }

            function init() {
                starSky = new StarSky();
                onResize();
                window.addEventListener("resize", onResize);

                document.getElementById("bgColor").addEventListener("change", function() {
                    document.body.style.backgroundColor = event.target.value;
                });
                document.getElementById("starColor").addEventListener("change", function() {
                    starSky.starColor = event.target.value;
                });

                var starShapeRadios = document.getElementsByName("starShapes");
                for(var i=0; i<starShapeRadios.length; i++) {
                    starShapeRadios[i].addEventListener("change", onStarShapeChange);
                }
                var starAnimationSchemes = document.getElementsByName("starAnimationSchemes");
                for(var i=0; i<starAnimationSchemes.length; i++) {
                    starAnimationSchemes[i].addEventListener("click", onStarAnimationSchemeClick);
                }

                document.getElementById("towardStepRange").addEventListener("change", function(){
                    document.getElementById("towardStepTip").innerHTML = "Toward Step:" + event.target.value;
                    starSky.towardStep = event.target.value;
                });
            }

            init();
        </script>
    </body>
</html>

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值