【注意】
本作代码需要在服务器端执行,不可用浏览器直接打开运行。
如何安装服务器端请参考: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(){// 获得imgvar img = document.getElementById("maxim");// 用于从中取图片数据的隐藏canvasvar hideCanvas=document.getElementById('hideCanvas'); hideCanvas.width=img.width;hideCanvas.height=img.height; hideCtx=hideCanvas.getContext('2d'); hideCtx.drawImage(img,0,0);// 真正用于画图的Canvasvar 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