关于canvas 粒子聚合成完整图像的实例


这是在上篇随笔的第三种方法下进行改进的。

上篇说到的方法是在easel.js的框架下写的粒子不规则运动效果。

这是效果图:

现在要做的,就是将这里面运动的粒子聚合在一起,形成一张完整的图像。

这里我会把我实现的整个过程写下来,最后会贴整个代码,基本每行都会加上注释,以便能快速看懂,写的不好的地方希望能理解,以后多多改进。

写这样的效果,原理是很重要的,这其中最重要的就是 getImageData 这个方法。不明白这个方法的,可以去 http://www.w3school.com.cn/tags/canvas_getimagedata.asp 这里看明白后再继续看下文。

         getImagedata:function(){
                    //这里是原生的方法
                    var c=document.getElementById("canvas");
                    var ctx=c.getContext("2d");
                    var img = new Image();
                    img.src="../img/111.png";
                    img.onload=function(){
                        //canvas里面插入图像;
                        ctx.drawImage(img,0,0,page.imgWidth,page.imgHeight);
                        //获取图像每个像素的rgba
                        var imgData=ctx.getImageData(0,0,page.imgWidth,page.imgHeight);
                        //清除插入的图像后执行主函数
                        ctx.clearRect(0,0,page.imgWidth,page.imgHeight);
                        page.canVas._canvas();
                        //将透明度大于50的像素点位置存入数组page.dots;
                        //x+=2,y+=2;隔一个像素点取值。
                        for(var x=0;x<page.imgWidth;x+=2){
                            for(var y=0;y<=page.imgHeight;y+=2){
                                var i = (y*imgData.width + x)*4;
                                if(imgData.data[i+3] >= 50){
                                    var dot=[];
                                    dot[0]=x;
                                    dot[1]=y;
                                    page.dots.push(dot);
                                }
                            }
                        }
                    }
                }

这段代码的目的,就是获取透明度大于50的像素点,并将他的位置存储起来,以便后面的粒子能够运动到该位置。

写到这里,忽然就不想写了,因为发现我代码里基本都注释好了。算了直接上代码吧,这里上两份完整的代码,第一份是我做的时候用来过度的,我把它保留下来了,第二份是在第一份的基础上,稍微改了几行代码,形成的最终效果。

第一份,用来过度的代码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>4</title>
    <meta name="format-detection" content="telephone=no">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=0,minimum-scale=1.0,maximum-scale=1.0,minimal-ui" />
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <link rel="stylesheet" href="../css/main.css"/>
</head>
<body class="hidden re">
<canvas class="ab hide" id="canvascopy"></canvas>
<canvas class="ab" id="canvas"></canvas>

<script src="../js/zepto.min.1.js"></script>
<script src="../js/createjs-2015.11.26.min.js"></script>
<script>
    $(document).ready(function(){
        var pageH,pageW;
        page= {
            init: function () {
                ////阻止body滑动
                $('body').on("touchmove", function (e) {
                    e.preventDefault();
                });
                window.addEventListener("touchstart", function (e) {
                    e.preventDefault();
                });
                $(window).resize(function () {
                    page.resize();
                });
                //设置粒子生成的图像的宽高
                page.imgWidth = 100;
                page.imgHeight = 100;
                //存储用来生成图像的粒子的位置
                page.dots=[];
                page.click=0;
                //用来存储圆点
                page.circleArray=[];
                //设置圆点数量
                page.circleLength = 2000;
                page.resize();
                page.canVas.init();
            },
            canVas:{
                init:function(){
                    page.canVas.getImagedata();
                    //page.canVas._canvas();
                    //点击屏幕粒子聚合,分散
                    $("body").on("click",function(){
                        page.click=!page.click;
                    })
                },
                _canvas:function(){
                    stage = new createjs.Stage("canvas");
                    //循环定义圆点的属性;
                    for(var i= 0;i< page.circleLength;i++){
                        //随机圆点颜色
                        var color = "rgba(" + Math.floor(Math.random()*255) + "," + Math.floor(Math.random()*255) + ","+ Math.floor(Math.random()*255) +","+Math.random()+")";
                        //随机半径
                        var radius = Math.random()+0.5;
                        //随机初始位置
                        var x = Math.random()*pageW;
                        var y = Math.random()*pageH;
                        //随机每个点的“移动速度跟方向”
                        var movex = (1-Math.random()*2)*0.5;
                        var movey = (1-Math.random()*2)*0.5;
                        //画点
                        var particle = page.canVas._drawCircle(color, radius,x,y,movex,movey);
                        //将点存入数组,用于后面调用
                        page.circleArray.push(particle);
                        //添加形状实例到舞台显示列表
                        stage.addChild(particle);
                    }
                    //帧率
                    createjs.Ticker.setFPS(60);
                    //更新阶段将呈现下一帧
                    createjs.Ticker.addEventListener("tick", page.canVas.tick);

                },
                //圆点函数
                _drawCircle:function(color, radius,x,y,movex,movey){
                    var particle = new createjs.Shape();
                    particle.graphics.beginFill(color).drawCircle(0, 0, radius);
                    particle.x = x;
                    particle.y = y;
                    particle.movex = movex;
                    particle.movey = movey;
                    return particle;

                },
                //圆点移动
                tick:function(){
                    //粒子游离
                    if(page.click==0){
                        page.canVas.animate(0)
                    }else{//粒子聚合成图像
                        //粒子数大于图像有效像素点数
                        if(page.dots.length<page.circleLength){
                            page.canVas.animate2(page.dots.length)
                            page.canVas.animate(page.dots.length)
                        }else{//粒子数小于图像有效像素点数
                            page.canVas.animate2(page.circleLength)
                        }
                    }
                    //刷新
                    stage.update();
                },
                //粒子生成图像的动画;
                animate2:function(num){
                    for(var j= 0;j< num;j++){
                        //图像居中
                        page.circleArray[j].x-=((page.circleArray[j].x-((page.dots[j][0])+(pageW/2-page.imgWidth/2)))/20);

                        page.circleArray[j].y-=((page.circleArray[j].y-((page.dots[j][1])+(pageH/2-page.imgHeight/2)))/20);
                    }
                },
                //初始动画;
                animate:function(num){
                    for(var i= num;i< page.circleLength;i++){
                        //x轴方向,不同方向,不同速度移动
                        page.circleArray[i].x+=page.circleArray[i].movex;
                        //超出屏幕,从另一边出来,循环
                        if(page.circleArray[i].x>=pageW){
                            page.circleArray[i].x=0
                        }else if(page.circleArray[i].x<=0){
                            page.circleArray[i].x=pageW
                        }
                        //Y轴方向,不同方向,不同速度移动
                        page.circleArray[i].y+=page.circleArray[i].movey;
                        if(page.circleArray[i].y>=pageH){
                            page.circleArray[i].y=0
                        }else if(page.circleArray[i].y<=0){
                            page.circleArray[i].y=pageH
                        }
                    }
                },
                //获取有效像素点位置
                getImagedata:function(){
                    //这里是原生的方法
                    var c=document.getElementById("canvas");
                    var ctx=c.getContext("2d");
                    var img = new Image();
                    img.src="../img/111.png";
                    img.onload=function(){
                        //canvas里面插入图像;
                        ctx.drawImage(img,0,0,page.imgWidth,page.imgHeight);
                        //获取图像每个像素的rgba
                        var imgData=ctx.getImageData(0,0,page.imgWidth,page.imgHeight);
                        //清除插入的图像后执行主函数
                        ctx.clearRect(0,0,page.imgWidth,page.imgHeight);
                        page.canVas._canvas();
                        //将透明度大于50的像素点位置存入数组page.dots;
                        //x+=2,y+=2;隔一个像素点取值。
                        for(var x=0;x<page.imgWidth;x+=2){
                            for(var y=0;y<=page.imgHeight;y+=2){
                                var i = (y*imgData.width + x)*4;
                                if(imgData.data[i+3] >= 50){
                                    var dot=[];
                                    dot[0]=x;
                                    dot[1]=y;
                                    page.dots.push(dot);
                                }
                            }
                        }
                    }
                }
            },
            resize: function () {
                pageH = $(window).height();
                pageW = $(window).width();
                $(".page").width(pageW).height(pageH);
                $('canvas').attr('width', pageW).attr('height', pageH)
            }
        };
        page.init();
    });
</script>
</body>
</html>

这里得到的效果是这样的:

这是链接:https://chuyunshi.github.io/Example/chuyunshi-canvas/demo/demo4.html

第二份:这是一份自己想要的效果,等有时间在给他改进改进,做点其他的效果

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>5</title>
    <meta name="format-detection" content="telephone=no">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=0,minimum-scale=1.0,maximum-scale=1.0,minimal-ui" />
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <link rel="stylesheet" href="../css/main.css"/>
</head>
<body class="hidden re">
<canvas class="ab hide" id="canvascopy"></canvas>
<canvas class="ab" id="canvas"></canvas>

<script src="../js/zepto.min.1.js"></script>
<script src="../js/createjs-2015.11.26.min.js"></script>
<script>
    $(document).ready(function(){
        var pageH,pageW;
        page= {
            init: function () {
                ////阻止body滑动
                $('body').on("touchmove", function (e) {
                    e.preventDefault();
                });
                window.addEventListener("touchstart", function (e) {
                    e.preventDefault();
                });
                $(window).resize(function () {
                    page.resize();
                });
                //设置粒子生成的图像的宽高
                page.imgWidth = 100;
                page.imgHeight = 100;
                //存储用来生成图像的粒子的位置
                page.dots=[];
                page.click=0;
                //用来存储圆点
                page.circleArray=[];
                //设置圆点数量
                page.circleLength = 0;
                page.resize();
                page.canVas.init();
            },
            canVas:{
                init:function(){
                    page.canVas.getImagedata();
                    //page.canVas._canvas();
                    //点击屏幕粒子聚合,分散
                    $("body").on("click",function(){
                        page.click=!page.click;
                    })
                },
                _canvas:function(){
                    stage = new createjs.Stage("canvas");
                    //循环定义圆点的属性;
                    for(var i= 0;i< page.circleLength;i++){
                        //随机圆点颜色
                        var color = "rgba(" + page.dots[i][2] + "," + page.dots[i][3] + ","+ page.dots[i][4] +","+page.dots[i][5]+")";
                        //随机半径
                        var radius = 1;
                        //随机初始位置
                        var x = Math.random()*pageW;
                        var y = Math.random()*pageH;
                        //随机每个点的“移动速度跟方向”
                        var movex = (1-Math.random()*2)*0.5;
                        var movey = (1-Math.random()*2)*0.5;
                        //画点
                        var particle = page.canVas._drawCircle(color, radius,x,y,movex,movey);
                        //将点存入数组,用于后面调用
                        page.circleArray.push(particle);
                        //添加形状实例到舞台显示列表
                        stage.addChild(particle);
                    }
                    //帧率
                    createjs.Ticker.setFPS(60);
                    //更新阶段将呈现下一帧
                    createjs.Ticker.addEventListener("tick", page.canVas.tick);

                },
                //圆点函数
                _drawCircle:function(color, radius,x,y,movex,movey){
                    var particle = new createjs.Shape();
                    particle.graphics.beginFill(color).drawCircle(0, 0, radius);
                    particle.x = x;
                    particle.y = y;
                    particle.movex = movex;
                    particle.movey = movey;
                    return particle;

                },
                //圆点移动
                tick:function(){
                    //粒子游离
                    if(page.click==0){
                        page.canVas.animate(0)
                    }else{//粒子聚合成图像
                        //粒子数大于图像有效像素点数
                        if(page.dots.length<page.circleLength){
                            page.canVas.animate2(page.dots.length)
                            page.canVas.animate(page.dots.length)
                        }else{//粒子数小于图像有效像素点数
                            page.canVas.animate2(page.circleLength)
                        }
                    }
                    //刷新
                    stage.update();
                },
                //粒子生成图像的动画;
                animate2:function(num){
                    for(var j= 0;j< num;j++){
                        //图像居中
                        page.circleArray[j].x-=((page.circleArray[j].x-((page.dots[j][0])+(pageW/2-page.imgWidth/2)))/20);

                        page.circleArray[j].y-=((page.circleArray[j].y-((page.dots[j][1])+(pageH/2-page.imgHeight/2)))/20);
                    }
                },
                //初始动画;
                animate:function(num){
                    for(var i= num;i< page.circleLength;i++){
                        //x轴方向,不同方向,不同速度移动
                        page.circleArray[i].x+=page.circleArray[i].movex;
                        //超出屏幕,从另一边出来,循环
                        if(page.circleArray[i].x>=pageW){
                            page.circleArray[i].x=0
                        }else if(page.circleArray[i].x<=0){
                            page.circleArray[i].x=pageW
                        }
                        //Y轴方向,不同方向,不同速度移动
                        page.circleArray[i].y+=page.circleArray[i].movey;
                        if(page.circleArray[i].y>=pageH){
                            page.circleArray[i].y=0
                        }else if(page.circleArray[i].y<=0){
                            page.circleArray[i].y=pageH
                        }
                    }
                },
                //获取有效像素点位置
                getImagedata:function(){
                    //这里是原生的方法
                    var c=document.getElementById("canvas");
                    var ctx=c.getContext("2d");
                    var img = new Image();
                    img.src="../img/111.png";
                    img.onload=function(){
                        //canvas里面插入图像;
                        ctx.drawImage(img,0,0,page.imgWidth,page.imgHeight);
                        //获取图像每个像素的rgba
                        var imgData=ctx.getImageData(0,0,page.imgWidth,page.imgHeight);
                        //清除插入的图像后执行主函数
                        ctx.clearRect(0,0,page.imgWidth,page.imgHeight);
                        //将透明度大于50的像素点位置存入数组page.dots;
                        //x+=2,y+=2;隔一个像素点取值。
                        for(var x=0;x<page.imgWidth;x+=2){
                            for(var y=0;y<=page.imgHeight;y+=2){
                                var i = (y*imgData.width + x)*4;
                                if(imgData.data[i+3] >= 50){
                                    var dot=[];
                                    dot[0]=x;
                                    dot[1]=y;
                                    dot[2]=imgData.data[i];
                                    dot[3]=imgData.data[i+1];
                                    dot[4]=imgData.data[i+2];
                                    dot[5]=imgData.data[i+3];
                                    page.dots.push(dot);
                                }
                            }
                        }
                        //将粒子数设置成图像有效像素点数(建议粒子数不要超过2000,数值太大,会卡死)
                        page.circleLength = page.dots.length;
                        page.canVas._canvas();
                    }
                }
            },
            resize: function () {
                pageH = $(window).height();
                pageW = $(window).width();
                $(".page").width(pageW).height(pageH);
                $('canvas').attr('width', pageW).attr('height', pageH)
            }
        };
        page.init();
    });
</script>
</body>
</html>

效果图:

 

这是链接:https://chuyunshi.github.io/Example/chuyunshi-canvas/demo/demo5.html

以及多写了个链接:https://chuyunshi.github.io/Example/chuyunshi-canvas/demo/demo6.html

不要改demo7.html了。这个是下篇的链接。//修改于2017/6/1/14:54

最后在这里说两句,这些都是我在网上一点点拼凑,一点点磨出来的,找到别人写的,基本都是没注释的,因为不知道他的思想,看他的代码也是有些费劲。这里我写注释也不是为了让别人看着方便,是为了让自己以后能看懂,以前写代码,我基本是很少注释的,自认为自己的结构很明确在这,不需要注释。后来慢慢的就发现注释还是很重要的。我写这些东西,是因为我发现,想学好一样新的东西,就要学着把它完整的介绍给下一个一点都不懂的人听,并能够让他很好的学会,这样才算自己也学好了,好吧,这个貌似我还没学好。好的,我说完了。聚合,离散的效果,点击屏幕就能看到,也懒得写按钮了

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM