专栏首页程序员的诗和远方Canvas基础-粒子动画Part1

Canvas基础-粒子动画Part1

网页上各种酷炫的粒子动画看的人眼花缭乱,实际上原理却非常简单。

获取像素信息

首先我们需要画张图到Canvas上,这里因为我懒的扣图(实际上是不会),就找了张jpeg的白底图片。实际上用png的透明图会好很多。

一定要等图片加载完再画,这很重要,可以用判断图片的complete属性和设置onload方法来等图片加载完才初始化。 另外绘制图片是有跨域限制的,本地看的话,要么你的图片服务器支持跨域,要么你就跑个本地服务器吧。

    var img = new Image();
    img.src = "images.jpeg";

    if(img.complete){
        init()
    } else {
        img.onload = function(){
            init()
        }
    }

图片获取完之后我们就可以开始获得图片的像素信息了,接口很简单:

context.getImageData(x,y,width,height)获得画布上指定矩形的像素数据。

    ctx.drawImage(img, sx, sy);
    var imgData = ctx.getImageData(sx, sy, imgW, imgH);

拿到像素数据,不要太简单好吗?! 因为这里我是把图片画在画布中间的,所以起始点不是(0,0),获得的矩形宽高则为图片的宽高。

打印出来看看数据是什么样子的。

首先返回的是个ImageData对象,属性有data和width,height,这还不是重点,data的类型是个Uint8ClampedArray(此处一脸蒙逼), 看起来是个二维数组,数组里面一堆的数字是什么鬼(二脸蒙逼)

还好有文档:

  • Uint8ClampedArray对象是一个8位无符号整数的类型化数组,里面的值都是0-255。
  • 这堆数字代表的是rgba的值,但是每个数字只代表一个,比如说第一个数字0,代表第一个像素的R值,第二个数字0代表第一个像素的G值,第三第四个0分别代表第一个像素的B值和Alpha值,最后出来第一个像素就是个全透明的颜色,第五个数字就代表第二个像素的R值了。

实际上,图像是二维的,是由height决定行数,width决定列像素的行列式。

做粒子动画首先需要把图片粒子化,把位置给找准,这样出来的东西才不会是乱七八糟的,所以我们拿到每个点的位置信息保存下来就可以了。

    for(var x=0; x<imgData.width; x+=6) {
        for(var y=0; y<imgData.height; y+=6) {
            var i = (y*imgData.width + x) * 4;
            if(imgData.data[i+3] > 128 && imgData.data[i] < 100){
                var dot = new Dot(x, y, 2);
                dotList.push(dot);
            }
        }
    }

两重循环就不说了,这里有几个地方简单解释一下:

  • 循环条件中有个x+=6,y+=6这里为什么不是1呢?因为是做粒子化,每个点之间需要有一些空隙才看的出来,所以不用每个点都拿,隔一段距离拿一个点就可以了,这里的6有点类似于取样的概念。
  • 内侧循环有个if判断语句,[i+3]指的是像素中Alpha的值,大于128是用于过滤掉一些透明像素的。后面那个imgData.data[i] < 100因为我用的是个白底黑字的jpeg文件,所以还需要把不像黑色的像素过滤掉,因为大都只有黑白两色,所以就简单判断了R值小于100,所以就像之前说的,还是用png图片比较好。
  • Dot对象是用来保存每取样的个像素点信息的,这里我只保存了x,y信息,第三个参数是半径的值,这里就直接写死了2,实际上还可以考虑保存像素点的rgba信息以及半径做个随机数。
    function Dot(centerX, centerY, radius) {
        this.x = centerX;
        this.y = centerY;
        this.radius = radius;
    }

最后一步就是把保存下来的信息画到Canvas上。

    function draw(){
        var imgW = img.width,
            imgH = img.height,
            sx = winWidth/2-imgW/2,
            sy = winHeight/2-imgH/2;

        ctx.clearRect(0, 0, winWidth, winHeight);

        ctx.fillStyle = "#000";

        for(var i=0; i<dotList.length; i+=1){
            curDot = dotList[i];
            ctx.save();
            ctx.beginPath();
            ctx.arc(sx+curDot.x, sy+curDot.y, curDot.radius, 0, 2*Math.PI);
            ctx.fill();
            ctx.restore();
        }
    }

最后出来的效果:

粒子化基本就写到这里,下篇讲讲用粒子化的东西做动画吧,最近事情比较多,懒癌又犯了。

源码地址: https://github.com/bob-chen/canvas-demo/blob/master/basic/particle-part1.html

参考

http://www.w3school.com.cn/tags/canvas_getimagedata.asp

https://msdn.microsoft.com/zh-cn/library/dn641188%28v=vs.94%29.aspx

http://www.cnblogs.com/axes/p/3500655.html

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Canvas基础-粒子动画Part3

    在上一篇文章 Canvas基础-粒子动画Part2 中讲了让图片做粒子动画。上篇写完不久,想起既然是用Canvas,写上去的东西都可以做粒子动画,那么就补充讲...

    Bob.Chen
  • Canvas画图-一个比想象中更骚气的圆(渐变圆环)

    之前介绍了Canvas画图基础,这篇介绍一下画一个带渐变效果的圆。 一个渐变的圆环 渐变色应用广泛,和圆环结合做进度条非常酷,今天我们就来画一个这样的圆环...

    Bob.Chen
  • 谈谈 JavaScript 中的 TDZ

    本来过年期间想写这个的,不过要准备些东西,一直没抽出时间,刚好今天有点空闲。上个月阮一峰阮老师在微博上发布了这样一条信息 于是评论区炸开了锅,很多人留言指出,这...

    Bob.Chen
  • Android自定义安全键盘

    六月的雨
  • 前端魔法堂:屏蔽Backspace导致页面回退

    前言  前几天用户反映在录入资料时一不小心错按Backspace键,就会直接回退到是一个页面,导致之前辛辛苦苦录入的资料全部丢失了。哦?居然还有这种情况。下面我...

    ^_^肥仔John
  • 弄它!!!静态路由原理与配置实验(华为ensp软件上手动配置静态路由)

    静态路由原理与配置 实验案例一:在华为ensp软件上手动配置静态IP 实验环境 如图所示,在华为ensp软件上将三个路由器进行环形连接,手动配置静态ip...

    不吃小白菜
  • Spring Cloud构建微服务架构:分布式服务跟踪(入门)

    通过之前的N篇博文介绍,实际上我们已经能够通过使用它们搭建起一个基础的微服务架构系统来实现我们的业务需求了。但是,随着业务的发展,我们的系统规模也会变得越来越大...

    程序猿DD
  • 【leetcode刷题】20T32-二进制求和

    https://leetcode.com/problems/add-binary/

    木又AI帮
  • 使用GDAL实现DEM的地貌晕渲图(一)

    以前一直以为对DEM的渲染就是简单的根据DEM的高度不同赋予不同的颜色就可以。后来实际这么做的时候获取的效果跟别的软件相比,根本体现不出地形起伏的变化。如果要体...

    charlee44
  • [信息安全] 4.一次性密码 && 身份认证三要素

    在信息安全领域,一般把Cryptography称为密码,而把Password称为口令。日常用户的认知中,以及我们开发人员沟通过程中,绝大多数被称作密码的东西其...

    blackheart

扫码关注云+社区

领取腾讯云代金券