基于canvas使用粒子拼出你想要的文字

写在最前

本次分享一下使用canvas实现粒子效果拼出你想要的文字。

欢迎关注我的博客,不定期更新中——

起因

不久之前看到大搜车团队出品的easy mock产品的界面中有一个使用粒子拼出“mock so easy”的效果,感觉非常有意思,就像下面这样:

image

当然了,这个easy mock的界面中还有粒子汇聚、散开、以及缓动等效果,这些在之后的文章中会不定时的更新实现思路。

我当时看到这个效果的时候是一段单一的英文,不知道源码能不能支持自己配置需要的字符,故想自己实现一个可以配置的版本。

PS:突然想到作者之前也封装过一个输入一段英文,输出一段可表示该字母的“黑魔法代码”:效果就像下面这样:

_20170825233827

缘由也是网上有人用这种黑魔法代码拼出了单词,但是并不是“可配置”的,也就不能想要啥就是啥,故才有了作者的一版封装实现,文章如下:(相关代码在原文中提及

效果图

image

你可以任意输入你能想到的字符,只要打得进去:)

示例:


image
image

核心问题:怎么确定粒子的摆放位置?

emmmm作者目前想到的办法是:降低像素数

来看下这个“非常粗略”的示意图:

image

这是当我在页面输入“an"之后展示的隐藏的canvas的截图,我将其放入到了ps中并放大,我们可以清晰地看到该图是由一个个很小的像素点通过每个像素点不同的颜色最终绘制出来的。而我们要做的就是用更少的“像素点”来绘制同样的内容。也就是原来100✖️100像素的图,我们如果用25✖️25来表示,那么每个像素点就会粗很多,同时粒度也会更加宽泛,之后我们如果将像素点变为圆形,最后我们就可以得到如文章开头提到的那样,由一个个粒子“拼”出了效果。

总的来说就是通过将输入的信息转化为图片后,读取图片的像素信息,同时粗略的将图片分块,遍历每块区域中的像素点判断该块是否需要画一个粒子。届时所有区域遍历完毕就可以用比像素点少很多的粒子来大体表示每一个输入的字符。那么具体实现过程如下:

  • 将输入的文字转化为图片插入到一个隐藏的canvas中
  • 按一定比例如(4像素✖️4像素)分割该canvas图像,形成一个拥有x * y个格子的区域,每个格子中拥有一定像素数(4✖️4 = 16)
  • 读取该canvas中的图片像素数据
  • 获取在每一个格子中拥有除灰度颜色的像素数(白底或者黑底属于插入到canvas中的图片的背景)
  • 当一个格子中有颜色的像素数占所有像素的一定程度后,认定该区域属于输入字符的一部分,则在该区域画一个粒子,否则不画

实现过程

文字转化为图片插入canvas

function loadCanvas(value) {
    var fontSize = 100,
        width = calWordWidth(value, fontSize), 
        canvas = document.createElement('canvas')
    canvas.id = 'b_canvas'
    canvas.width = width 
    canvas.height = fontSize
    var ctx = canvas.getContext('2d')
    ctx.font = fontSize + "px Microsoft YaHei"
    ctx.fillStyle = "orange"
    ctx.fillText(value, 0, fontSize / 5 * 4) //轻微调整绘制字符位置
    getImage(canvas, ctx) //导出为图片再导入到canvas获取图像数据
}
function getImage(canvas, ctx) {
    var image = new Image()
    image.src = canvas.toDataURL("image/jpeg") //canvas导出
    image.onload = function() {
        ... 
    }
}

降低像素数

var imageData = ctx.getImageData(0, 0, this.width, this.height)
var dataLength = imageData.data.length
var diff = 4 //按4✖️4划分区域,可自行改变尝试
var newCanvas = document.getElementById('canvas')
var newCtx = newCanvas.getContext('2d')
for (var j = 0; j < this.height; j += diff) { //height为canvas高
    for (var i = 0; i < this.width; i += diff) {//width为canvas宽
        var colorNum = 0
        for (var k = 0; k < diff * diff; k++) {
            var row = k % diff
            var col = ~~(k / diff)
            let r = imageData.data[((j + col) * this.width + i + row) * 4 + 0]
            let g = imageData.data[((j + col) * this.width + i + row) * 4 + 1]
            let b = imageData.data[((j + col) * this.width + i + row) * 4 + 2]
            if (r < 10 && g < 10 && b < 10) colorNum++ 
            //如果满足此条件说明当前为背景色黑色(canvas转出来的图片背景并不是纯黑的
        }
        if (colorNum < diff * diff / 3 * 2) {
        //黑色背景占比小于一定程度说明此处应该画粒子,占比度可自行调整
            var option = {
                x: i,
                y: j,
                radius: 6,
                color: '#fff'
            }
            var newBubble = new Bubble(option)
            newBubble.draw(newCtx) //画粒子
        } 
    }
}

其他canvas相关文章

最后

源代码见:https://github.com/Aaaaaaaty/Blog/blob/master/canvas/canvasImitateWord/main.js

本次只实现了可配置拼出字符的功能,粒子动态上没加入特效,其他效果实现思路之后可能会不定时更新——

惯例po作者的博客,不定时更新中——
有问题欢迎在issues下交流。

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

推荐阅读更多精彩内容