【Canvas与艺术】粒子特效-砂落字现

【注意】

本作代码需要在服务器端执行,不可用浏览器直接打开运行。

如何安装服务器端请参考:https://www.cnblogs.com/heyang78/p/3339235.html

【原理】

雨粒子落下时,如果当前点不是黑点,则化身为金字的一个像素点。

【效果】

【代码】

<!DOCTYPE html>
<html lang="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<head>
     <title>砂落字现粒子特效</title>
     </head>

     <body onload="draw()">
        <img id="maxim" src="71.maxim.png" style="display:none"/>
        <canvas id="hideCanvas"  style="display:none"></canvas>
        <canvas id="myCanvas" width="100px" height="100px" style="border:0px dashed black;">
            出现文字表示您的浏览器不支持HTML5
        </canvas>
     </body>
</html>
<script type="text/javascript">
<!--
/*****************************************************************
* 将全体代码(从<!DOCTYPE到script>)拷贝下来,粘贴到文本编辑器中,
* 另存为.html文件,再用chrome浏览器打开,就能看到实现效果。
******************************************************************/

// 画布宽
var Width=1200;

// 画布高
var Height=512;

// 绘图上下文
var context;

// 舞台对象
var stage;

// 肇始函数
function draw(){
    // 获得img
    var img = document.getElementById("maxim");

    // 用于从中取图片数据的隐藏canvas
    var hideCanvas=document.getElementById('hideCanvas');  
    hideCanvas.width=img.width;
    hideCanvas.height=img.height; 
    hideCtx=hideCanvas.getContext('2d');  
    hideCtx.drawImage(img,0,0);

    // 真正用于画图的Canvas
    var canvas=document.getElementById('myCanvas');    
    Width=img.width;
    Height=img.height;
    canvas.width=Width;
    canvas.height=Height;    
    context=canvas.getContext('2d');    
    
    // 准备
    stage=new Stage(10000);    
    stage.init();

    // 开幕
    animate();
};

// 循环播放动画
function animate(){    
    // 直接清屏则无拖尾效果
    //context.clearRect(0,0,Width,Height);    

    // 加上半透明蒙层带上的拖尾效果
    context.fillStyle = 'rgb(0,0,0,.07)'   
    context.rect(0, 0, Width, Height) 
    context.fill()  

    stage.update();
    stage.paintBg(context);
    stage.paintFg(context);     

    if(true){
        window.requestAnimationFrame(animate);
    }
}

// 舞台类
function Stage(count){
    // 雨粒子数组
    this.rainArr=new Array(count);

    // 金粒子数组
    this.goldenArr=new Array(count);
    
    // 初始化
    this.init=function(){
        for(var i=0;i<this.rainArr.length;i++){
            var item={};
            item.x=Math.random()*Width;
            item.y=Math.random()*Height;
            item.vy=Math.random()*10+1;

            this.rainArr[i]=item;
        }
    }

    // 更新粒子的位置
    this.update=function(){
        this.rainArr.forEach(function (item, i) {
            // 下坠
            item.y+=item.vy;

            // 取当前点的像素
            let data = hideCtx.getImageData(item.x,item.y,1,1).data;

            // 如果RGB不都等于0,说明当前坐标是金字位置
            if(data[0]!=0 || data[1]!=0 || data[2]!=0){
                var pt={};
                pt.x=item.x;
                pt.y=item.y;
                stage.goldenArr.push(pt);// 保存此点

                // 原像素点置黑,此举是为了金沙能继续下落
                var blackImageData=new ImageData(1,1);
                blackImageData.data[0]=0;
                blackImageData.data[1]=0;
                blackImageData.data[2]=0;
                hideCtx.putImageData(blackImageData,item.x,item.y);

                // 显影归零
                item.y=0;
                item.x=Math.random()*Width;
            }

            // 越界归零
            if(item.y>Height){
                item.y=0;
                item.x=Math.random()*Width;
            }
        })        
    };

    //  画背景
    this.paintBg=function(ctx){
        // 背景黑色
        ctx.fillStyle="black";
        ctx.fillRect(0,0,Width,Height);

        ctx.fillStyle="White";
        ctx.fillText("砂落字现 by:逆火",Width-100,Height-20);
    };


    // 画前景
    this.paintFg=function(ctx){
        this.rainArr.forEach(function (item, i) {
            ctx.fillStyle="yellow";
            ctx.fillRect(item.x,item.y,2,2);
        })    
        
        this.goldenArr.forEach(function (pt, i) {
            ctx.fillStyle="yellow";
            ctx.fillRect(pt.x,pt.y,1,1);
        })
    };
}

/*----------------------------------
自开天辟地以来,
炼狱与世人同在,
时间与牛马同行,
周而复始,昼夜不息...
----------------------------------*/
//-->
</script>

【需要用到的底图】

请将上图另存为 71.maxim.png,与代码配合使用。

【参考资料】

https://www.cnblogs.com/heyang78/p/7599468.html

https://blog.csdn.net/jimojianghu/article/details/128700697

END

posted @ 2024-03-17 22:55  逆火狂飙  阅读(7)  评论(0编辑  收藏  举报
生当作人杰 死亦为鬼雄 至今思项羽 不肯过江东