canvas 文字粒子特效

转自博客原文连接:https://tong-h.github.io/2019/04/23/canvas-fontparticle/

想要往仓库多填一些干货,一个文字粒子效果 点这里看效果

效果图

随机初始化部分粒子

1、首先要明白每个粒子都是一个对象,都有自己的移动轨迹,起点,移动速度,终点

2、粒子活动轨迹:初始化 ---- 聚合拼合文字形状 ---- 散开 ---- 再聚合 ---- 散开...

3、我们需要根据动画时间调整粒子移动的速度来安排他们的位置

    class Point{
        constructor() {
            this.startx = Math.floor(Math.random() * docsize[0]),   // 初始起点
            this.starty = Math.floor(Math.random() * docsize[1]),
            this.speedx = (Math.random() * 2 - 1) * pointspeed,     // 移动速度
            this.speedy = (Math.random() * 2 - 1) * pointspeed, 
            this.endx = 0,                                          // 终点
            this.endy = 0,                    
            this.color = Math.floor(Math.random() * 5)              // 粒子颜色
        }
        endpoint(x, y) {
            this.endx = x
            this.endy = y
        }
        animal() {
            this.startx += this.speedx
            this.starty += this.speedy

            // 到达边界改变粒子运动方向
            this.speedx *= this.startx > docsize[0] || this.startx < 0 ? -1 : 1
            this.speedy *= this.starty > docsize[1] || this.starty < 0 ? -1 : 1

            // 调整点的移动速度用以聚和拼合文字
            if(time === 100 || time === 600 || time === 1100) { 
                this.speedx = (this.endx - this.startx) / joinspeed
                this.speedy = (this.endy - this.starty) / joinspeed
            }

            // 到达终点后静止不动
            if(time === 100 + joinspeed || time === 600 + joinspeed || time === 1100 + joinspeed) {
                this.speedx = 0
                this.speedy = 0
            }

            // 散开
            if(time === 300 || time === 800) {
                this.speedx = (Math.random() * 2 - 1) * pointspeed
                this.speedy = (Math.random() * 2 - 1) * pointspeed
            }

            maincontent.beginPath()
            maincontent.fillStyle = color[this.color]
            maincontent.arc(this.startx, this.starty, 7, 0, Math.PI * 2)
            maincontent.fill()
        }
    }

使用 canvas 画板生成文字

// 【文字面积,循环时用于判读y轴高度,粒子大小间隔, 文字宽度】
let [imgdata, cyclic, size, textwith] = [{}, 1, 16, 0]

textcontext.font = "normal 900 " + fontsize +"px Avenir, Helvetica Neue, Helvetica, Arial, sans-serif"
textwith = Math.floor(textcontext.measureText(text).width)
textcontext.fillStyle = '#ff0000'
textcontext.fillText(text, (docsize[0] - textwith) / 2, (docsize[1]) / 2)
textwith = ~~ (textwith) * size + size

遍历 imageData 获取文字区域的像素坐标

不了解 imagedata 怎么用? 看看这篇文章cannvas的imagedata对象

获取坐标这里有很多种方法,我看了一些教程好像没人像我这么写,要注意的是

  • imageData 4个元素为一个像素,也就是一个R G B A 值,A 是 alpha 透明度
  • 空白的区域rgba就是 0,0,0,0 , 文字区域就是有颜色的如果你没有设置字体颜色默认是黑色 rgba 就是 0,0,0,255,通过判断第四个元素可以获取文字区域
  • 但是我建议重新设置一个其他的颜色比如红色 255,0,0,255,用第1个和2个数字来判断这样字体边缘会圆滑些,因为在字体边缘黑色和白色的交界处可能有某几个像素不是透明的
  • 每个坐标最后都会生成一个圆,所以这里获取的是圆心的坐标,圆之间还需要留有空隙,所以遍历的时候你要根据你的圆的大小掌握好间隔
  • 获取文字区域粒子数量后需要判断,目前屏幕上现有的粒子是否足够拼合和文字或者是否还需再添加粒子
  • 确定粒子数量后再将文字坐标作为粒子移动终点赋值给粒子
// 获取文字所在区域,尽可能减小面积
imgdata = textcontext.getImageData(0,0, textwith, fontsize * 2)
textcontext.clearRect(0, 0, docsize[0], docsize[1])

// 粒子圆心坐标,粒子数组
let [x, y, len] = [0, 0, 0]

// 遍历data数据查找文字所在的坐标
for (var i = 0; i < imgdata.data.length; i += size * 4) {
    if (imgdata.data[i] === 255 && imgdata.data[i+3] === 255) {

        // 判断当前粒子数量是否能够拼合文字
        if (len > pointarr.length - 1) pointarr.push(new Point)

        // 获取每个粒子聚拢的终点
        pointarr[len].endpoint(i /4 % textwith, cyclic)
        len ++
    }
    if (i/4 == cyclic * textwith) {
        cyclic += size
        i = textwith * (cyclic-1) * 4
    } 
}

pointarr.length - 1 - len > 0 ? pointarr.splice(len, pointarr.length - len) : ''

源码带有详细的注解点这儿

更多效果
开源不易,觉得还不错点个 start 吧 (´▽`ʃ♡ƪ)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,475评论 4 372
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,744评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,101评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,732评论 0 221
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,141评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,049评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,188评论 2 320
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,965评论 0 213
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,716评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,867评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,341评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,663评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,376评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,200评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,990评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,179评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,979评论 2 279