canvas - 炫酷的3D星空

Posted 寒玉知

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了canvas - 炫酷的3D星空相关的知识,希望对你有一定的参考价值。

1.国际惯例,先上效果

http://www.hanguozhi.com/plug-in/3D_nightSky/index.html

 

(⊙o⊙)… 效果图看上去效果并不很炫酷啊,直接戳 这里 看效果吧!

2代码部分

 html: 

<canvas id="canvas" width="1920" height="1080"></canvas>

css:

*{margin: 0;padding: 0;}
/*没啥必须的css*/

js:(这个博主也是够了,那么多的js代码,一点注释都没有,差评!)公子莫慌,由于代码比较多,注释部分就不在这写啦,直接移步 效果展示 查看效果及代码注释。

var Starry = function (canvasId, starCont) {
    this.renderLoop = null;
    this.framerate = 42;
    this.starfield = null;
    this.rings_y = 0;
    this.altitude = 0;
    this.preset = {
        radius : 600,
        fov : 260,
        cruise : 0.01,
        angle : 0.006,
        vert : -0.001,
        rings : 0.2
    };
    this.state = {
        width : document.documentElement.clientWidth,
        height : document.documentElement.clientHeight,
        altitude : 0,
        settings : this.preset,
        framerate : 50
    };
    var S = this
    if (!canvasId) return false
    S.canvas = document.getElementById(canvasId);
    S.canvas.width = document.documentElement.clientWidth;
    S.canvas.height = document.documentElement.clientHeight;
    S.ctx = S.canvas.getContext(\'2d\');
    this.starfield = this.generateStarfield();
}
Starry.prototype = {
    reset: function(){
        clearTimeout(this.renderLoop)
        this.state.width = this.canvas.width = document.documentElement.clientWidth;
        this.state.height = this.canvas.height = document.documentElement.clientHeight;
        this.init()
    },
    generateStarfield : function() {
        var radius = this.state.settings.radius;
        var star_count = Math.min( 1000, Math.round( this.canvas.offsetWidth / 2 ) );
        var stars = new Array( star_count );
        for (var i = 0; i < stars.length; i++) {
            stars[i] = {
                x: ( Math.random() * ( radius * 2 ) ) - ( radius ),
                y: ( Math.random() * ( radius * 2 ) ) - ( radius ),
                z: ( Math.random() * ( radius * 2 ) ) - ( radius )
            }
        };
        return stars;
    },
    move : function ( stars ) {
        var angle = this.state.settings.angle;
        var vert = this.state.settings.vert;
        var fov = this.state.settings.fov;
        var cruise = this.state.settings.cruise;
        var radius = this.state.settings.radius;
        var cosRX = Math.cos(angle);
        var sinRX = Math.sin(angle);
        var cosRY = Math.cos(vert);
        var sinRY = Math.sin(vert);
        return stars.map( function(star){
          var tempx = star.x;
          var tempy = star.y;
          var tempz = star.z + fov;
    
          var x = ( tempx * cosRX ) + ( tempz * sinRX );
          var y = ( tempy * cosRY ) + ( tempz * sinRY );
    
          // Depth based on X
          // var z = ( tempx * -sinRX ) + ( tempz * cosRX );
    
          // Depth based on Y
          var z = ( tempy * -sinRY ) + ( tempz * cosRY ) - cruise;
    
          var limit = radius;
    
          // x
          if ( x < -limit ) x = limit;
          else if ( x > limit ) x = -limit;
    
          // y
          if ( y < -limit ) y = limit;
          else if ( y > limit ) y = - limit;
    
          // z
          if ( z < -limit ) z = limit;
          else if ( z > limit ) z = -limit;
    
          return { x:x, y:y, z: z - fov };
        });
    },
    run: function () {
        var S = this;
        var width = this.state.width
        var height = this.state.height
        var fov = this.state.settings.fov
        var rings = this.state.settings.rings
        
        S.ctx.clearRect(0, 0, width, height);
        S.starfield.forEach(function(item, index){
            
          var scale = ( fov / 2 ) / ( fov + item.z );
          var x2d = ( item.x * scale ) + ( width / 2 );
          var y2d = ( item.y * scale ) + ( height / 2 );
          var opacity = Math.min( Math.max( Math.abs( scale ), 0.1 ), 1 );
          
          S.ctx.beginPath();
          S.ctx.arc(x2d, y2d, Math.min( Math.abs( scale ), 3 ) , 0, 360);
          S.ctx.fillStyle = \'rgba(167,180,224,\'+opacity+\')\';
          S.ctx.fill();
        })
        
        var ring_radius = height * 1.6;
        var ring_center = { x: width / 4, y: height * 2 };
        
        S.ctx.beginPath();
        S.ctx.arc( ring_center.x, ring_center.y + this.rings_y, ring_radius, 0, 360);
        S.ctx.lineWidth = 1;
        S.ctx.strokeStyle = \'rgba(167,180,224,0.15)\';
        S.ctx.stroke();
        S.ctx.beginPath();
        S.ctx.arc( ring_center.x + 60, ring_center.y + 60 + ( this.rings_y * 0.8 ), ring_radius, 0, 360);
        S.ctx.lineWidth = 1;
        S.ctx.strokeStyle = \'rgba(167,180,224,0.05)\';
        S.ctx.stroke();
        this.rings_y += rings;
        if( this.rings_y > ( width / 2 ) ) {
            this.rings_y = -( width/ 2 )
        };
        
        S.starfield = S.move( S.starfield )
        var _this = this;
        this.renderLoop = setTimeout(function (){_this.run()}, _this.state.framerate)
    },
    init: function () {
        this.run();
    },
    pause: function () {
        var _this = this;
        clearTimeout(_this.renderLoop)
    }
}

var starbg = new Starry (\'canvas\', 100);
window.onload = function () {
    starbg.init();
} 
window.onresize = function () {
    starbg.reset();
}

 

 (未完)

以上是关于canvas - 炫酷的3D星空的主要内容,如果未能解决你的问题,请参考以下文章

初级开发者也能码出专业炫酷的3D地图吗?

教你做炫酷的碎片式图片切换 (canvas)

canvas,制作炫酷的时钟和倒计时

七款炫酷的页面特效

非常炫酷的网页样式特效

一个简单炫酷的前端小项目(html+css+js)----3D图片演示