【注意】
本作代码需要在服务器端执行,不可用浏览器直接打开运行。
如何安装服务器端请参考: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 οnlοad="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
Javascript中的图像数据对象:Image、ImageData 和 ImageBitmap_js image-CSDN博客
END