1

【Canvas技法】流星雨的实现

 1 month ago
source link: https://blog.51cto.com/u_7726611/10681266
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

【Canvas技法】流星雨的实现

精选 原创

科技之巅 2024-05-02 13:14:08 博主文章分类:代码艺术 ©著作权

文章标签 canvas 流星雨 文章分类 代码人生 阅读数126

【关键点】

流星的绘制,本质上还是绘制一条直线,但在渲染上有差别。

通常绘制直线都是给的固定颜色,绘制流星给的是渐变色,渐变色的开头是与背景色对比度明显的亮色,结尾是与背景色相同的暗色,中间渐变过去,这就形成了长尾流星的形状,另调整渐变色的位置和颜色能微调流星的形状。

让流星运动起来和质点运动一样,这就无需赘述。

【Canvas技法】流星雨的实现_canvas 流星雨
<!DOCTYPE html>
<html lang="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<head>
     <title>使用HTML5/Canvas绘制动态流星雨</title>
     <style type="text/css">
     .centerlize{
        margin:0 auto;
        width:1200px;
     }
     </style>
     </head>

     <body onload="init();">
        <div class="centerlize">
            <canvas id="myCanvas" width="12px" height="12px" style="border:1px dotted black;">
                如果看到这段文字说您的浏览器尚不支持HTML5 Canvas,请更换浏览器再试.
            </canvas>
            <img id="myImg" src="170.jpg" style="display:none;"/>
        </div>
     </body>
</html>
<script type="text/javascript">
<!--
/*****************************************************************
* 将全体代码(从<!DOCTYPE到script>)拷贝下来,粘贴到文本编辑器中,
* 另存为.html文件,再用chrome浏览器打开,就能看到实现效果。
******************************************************************/

// canvas的绘图环境
var ctx;

// 高宽
const WIDTH=512;
const HEIGHT=512;


// 舞台对象
var stage;

//-------------------------------
// 初始化
//-------------------------------
function init(){
    // 获得canvas对象
    var canvas=document.getElementById('myCanvas');  
    canvas.width=WIDTH;
    canvas.height=HEIGHT;

    // 初始化canvas的绘图环境
    ctx=canvas.getContext('2d');  
    ctx.translate(WIDTH/2,HEIGHT/2);// 原点平移

    // 准备
    stage=new Stage();    
    stage.init();

    // 开幕
    animate();
}

// 播放动画
function animate(){    
    stage.update();    
    stage.paintBg(ctx);
    stage.paintFg(ctx);     

    // 循环
    if(true){
        //sleep(100);
        window.requestAnimationFrame(animate);   
    }
}

// 舞台类
function Stage(){
    // 流星数组
    this.arr=[];

    // 初始化
    this.init=function(){
        this.arr=new Array();

        for(var i=0;i<25;i++){
            var shoot={};
            // 位置
            shoot.x=-WIDTH/2+WIDTH*Math.random();
            shoot.y=-HEIGHT/2+HEIGHT*Math.random();

            // 首尾长度
            shoot.length=100;

            // 倾角
            shoot.theta=Math.PI/6;

            // 设置速度
            var speed=10*Math.random()+1;
            shoot.vx=-speed*Math.cos(shoot.theta);
            shoot.vy=speed*Math.sin(shoot.theta);

            // 放入数组
            this.arr.push(shoot);
        }
    }

    // 更新
    this.update=function(){    
        for(var i=0;i<this.arr.length;i++){
            var shoot=this.arr[i];

            if(shoot.x<-WIDTH/2){
                // Plan A:越过左边界从右边返回,轨迹重合
                var h=shoot.y+HEIGHT/2;
                var w=h/Math.tan(shoot.theta);
                shoot.x=-WIDTH/2+w;
                shoot.y=-HEIGHT/2;

                // Plan B:越过左边界重新随机设置位置
                //shoot.x=-WIDTH/2+WIDTH*Math.random();
                //shoot.y=-HEIGHT/2+HEIGHT*Math.random();
            }

            shoot.x+=shoot.vx;
            shoot.y+=shoot.vy;
        }
    }

    // 画背景
    this.paintBg=function(ctx){
        ctx.clearRect(-WIDTH/2,-HEIGHT/2,WIDTH,HEIGHT);// 清屏    
    }

    // 画前景
    this.paintFg=function(ctx){
        // 黑底
        ctx.fillStyle = "black";
        ctx.fillRect(-WIDTH/2,-HEIGHT/2,WIDTH,HEIGHT);

        // 逐个绘制流星
        for(var i=0;i<this.arr.length;i++){
            var s=this.arr[i];
            var start=createPt(s.x, s.y);
            var end=createPt(s.x+s.length*Math.cos(s.theta),s.y-s.length*Math.sin(s.theta));

            // 设置从起点到终点的渐变色
            var lgrd = ctx.createLinearGradient(start.x,start.y,end.x,end.y);
            lgrd.addColorStop(0, "white");
            lgrd.addColorStop(0.2, "gray");
            lgrd.addColorStop(0.6, "black");

            // 绘制从起点到终点的直线,在渐变色的作用下直线会变成拖曳长尾的流星形状
            ctx.beginPath();
            ctx.moveTo(start.x,start.y);
            ctx.lineTo(end.x,end.y);
            ctx.lineWidth=2;
            ctx.lineCap="round";
            ctx.strokeStyle=lgrd;
            ctx.stroke();
        }

        writeText(ctx,WIDTH/2-30,HEIGHT/2-5,"逆火原创","8px consolas","white");// 版权
    }
}

/*----------------------------------------------------------
函数:创建一个二维坐标点
x:横坐标
y:纵坐标
Pt即Point
----------------------------------------------------------*/
function createPt(x,y){
    var retval={};
    retval.x=x;
    retval.y=y;
    return retval;
}

/*----------------------------------------------------------
函数:延时若干毫秒
milliseconds:毫秒数
----------------------------------------------------------*/
function sleep(milliSeconds) {
    const date = Date.now();
    let currDate = null;
    while (currDate - date < milliSeconds) {
        currDate = Date.now();
    } 
}

/*----------------------------------------------------------
函数:书写文字
ctx:绘图上下文
x:横坐标
y:纵坐标
text:文字
font:字体
color:颜色
----------------------------------------------------------*/
function writeText(ctx,x,y,text,font,color){
    ctx.save();
    ctx.textBaseline="bottom";
    ctx.textAlign="center";
    ctx.font = font;
    ctx.fillStyle=color;
    ctx.fillText(text,x,y);
    ctx.restore();
}

/*-------------------------------------------------------------
A股中真实的故事
有个企业,挂了个国企的名头曰中青旅,
花几亿收购了苏州一个园林,
然后把园林里的石头评估成数百亿重新入帐,
使得整个公司总资产过五百亿,
然后从数十个金融机构贷款四百多亿,
其后控制人跑路到香港,再跑路到海外,
留下一堆金融机构站在风中不知道怎么办......
--------------------------------------------------------------*/
//-->
</script>

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK