文字烟花特效,用 JS 代码示爱!程序员小姐姐用这个代码挽回了爱情~ - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ezshine
V2EX    推广

文字烟花特效,用 JS 代码示爱!程序员小姐姐用这个代码挽回了爱情~

  •  
  •   ezshine 2021-05-06 10:34:57 +08:00 3442 次点击
    这是一个创建于 1708 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

    之前我出了一个如何在网页里使用原生 JS 开发放烟花效果的教程。

    image.png

    竟然有一个前端小阿姨问我,如果想要烟花放出来是文字的话怎么实现,她要给男朋友做一个。

    好家伙,这狗粮洒一地呀

    171253fc29abd17b89974c04784db038.gif

    那狗粮不能我一个人吃,分享出来,大家一起吃。

    此文配有 视频教程,边吃边看,狗粮更香。

    互动话题

    你身边有这样的程序员小姐姐吗?

    1. 没有,你编的
    2. 有呀,我认识

    点击参与投票

    先改造一下烟花的源代码

    之前烟花源码里的核心是,我们在创建烟花粒子的时候,赋值了烟花绽放的原点x,y和圆形烟花的半径radius。在绘制烟花动效时,半径不断加大,烟花的动效就出来。

    //篇幅限制,仅展现部分代码 function createFireworks(x, y) { var count = 100; for (var i = 0; i < count; i++) { var p = {}; p.x = x; p.y = y; p.speed = (Math.random() * 5) + .4; p.radius = p.speed; } } function drawFireworks(){ for (var i = 0; i < particles.length; i++) { var p = particles[i]; var vx = Math.cos(p.radians) * p.radius; var vy = Math.sin(p.radians) * p.radius + 0.4; p.x += vx; p.y += vy; p.radius *= 1 - p.speed / 100; } } 

    但要实现文字烟花,我们一开始就要把烟花最后的x,y坐标全部精确的计算出来。所以这个烟花的绘制,我们要更改一下逻辑。在createFireworks阶段,就计算出单个粒子的起点 x,y终点 fx,fy

    代码修改后如下

    //篇幅限制,仅展现部分代码 function createFireworks(x, y){ var count = 100; for (var i = 0; i < count; i++) { var angle = 360 / count * i; var p = {}; p.x = x; p.y = y; p.radians = angle * Math.PI / 180; p.radius = Math.random()*81+50; p.fx = x + Math.cos(radians) * p.radius; p.fy = y + Math.sin(radians) * p.radius; } } function drawFireworks() { for (var i = 0; i < particles.length; i++) { var p = particles[i]; p.x += (p.fx - p.x)/10; p.y += (p.fy - p.y)/10-(p.alpha-1)*p.speed; } } 

    这样我们就完成了第一步改造,后续我们要把文字写在画布上,并且将其转换为点阵数组,也就是所有烟花粒子的终点坐标。

    画布绘制文字

    其实和之前那篇《使用 Javascript 制作 BadApple 字符画视频》的原理是一样的。通过canvas的 APIgetImageData来获得画布指定区域内的全部点阵信息(rgba数组)。

    createFireworks方法改造如下

    function createFireworks(x,y,text=""){ if(text!=""){ //绘制文字 }else{ //原有的烟花代码 } } 

    传递一个text参数,当此参数不为空时,我们进入文字烟花的绘制逻辑。

    var fOntSize= 120; var textHeight = fontSize; context.fOnt=fontSize+"px Verdana"; context.fillStyle = "#ffffff"; context.fillText(text,0,textHeight); 

    image.png

    获取点阵数组

    这样我们就能把字绘制在画布上了,接着我们使用getImageData来获得并裁剪点阵信息,因为我们只要一部分的点阵。

    var imgData = textctx.getImageData(0,0,textWidth,textHeight); for (var h = 0; h < textHeight; h+=gap) { for(var w = 0; w < textWidth; w+=gap){ var position = (textWidth * h + w) * 4; var r = imgData.data[position], g = imgData.data[position + 1], b = imgData.data[position + 2], a = imgData.data[position + 3]; } } 

    这样我们就拿到了画布里文字绘制区域的全部点阵数据,数据的格式为

    [r,g,b,a,r,g,b,a,r,g,b,a] 

    我们通过一个gap值来跳跃间隔裁剪数据。由于画布是黑色,所以r,g,b都为0的点阵我们就不绘制了,现在将间隔的点阵信息再次绘制到画布中。

    var fx = x + w - textWidth/2; var fy = y + h - textHeight/2; context.fillStyle = "#ffffff"; context.fillRect(fx,fy,1,1); 

    我们就会看见~

    image.png

    image.png

    太棒了,这就是我们最终需要的文字烟花粒子的终点信息呀!

    现在我们遍历全部的点阵,并创建烟花粒子吧!

    for (var h = 0; h < textHeight; h+=gap) { for(var w = 0; w < textWidth; w+=gap){ var position = (textWidth * h + w) * 4; var r = imgData.data[position], g = imgData.data[position + 1], b = imgData.data[position + 2]; if(r+g+b==0)continue; var p = {}; p.x = x; p.y = y; p.fx = x + w - textWidth/2; p.fy = y + h - textHeight/2; p.size = Math.floor(Math.random()*2)+1; p.speed = 1; setupColors(p); particles.push(p); } } 

    文字烟花来了

    至此,文字烟花效果,我们就实现了!!!

    2021-05-03 21_27_34.gif

    用它示爱!

    createFireworks(x, y,["杨幂","我爱你","永远"][Math.floor(Math.random()*3)]); 

    2021-05-03 22_26_55.gif

    关注我获取源码

    微信搜索“大帅老猿”并回复“烟花”即可获得本文全部源码

    28 条回复    2021-05-07 12:59:14 +08:00
    DIYgods
        1
    DIYgods  
       2021-05-06 10:36:58 +08:00   42
    看着感觉真可怜
    bug403
        2
    bug403  
       2021-05-06 10:42:35 +08:00
    可怜+1,我也不知为什么?
    ezshine
        3
    ezshine  
    OP
       2021-05-06 10:52:41 +08:00
    @DIYgods 是有点卑微的赶脚
    caroline1022
        4
    caroline1022  
       2021-05-06 11:01:56 +08:00
    标题党吧……人家也没说是挽回爱情啊,只是想给男朋友做个小礼物吧
    但有一说一……有点…不太好看…如果有人做了给我,我怕是会连夜跑路
    est
        5
    est  
       2021-05-06 11:02:50 +08:00   3
    挽救的是你公众号的流量吧。
    ezshine
        6
    ezshine  
    OP
       2021-05-06 11:04:05 +08:00
    @caroline1022 哈哈
    ezshine
        7
    ezshine  
    OP
       2021-05-06 11:04:33 +08:00
    @est 不是公众号,挽救一下 B 站,哈哈
    opengps
        8
    opengps  
       2021-05-06 11:33:25 +08:00
    好像也就面向于某些群体才能用代码挽回爱情。。。悲,,,
    Rxianbei
        9
    Rxianbei  
       2021-05-06 11:36:16 +08:00 via Android
    清醒一点,这只能挽回同性之间的爱情
    sheeta
        10
    sheeta  
       2021-05-06 12:04:12 +08:00   1
    @livid 推广
    domodomo
        11
    domodomo  
       2021-05-06 12:54:37 +08:00
    推广文案写得真烂
    icanfork
        12
    icanfork  
       2021-05-06 13:45:09 +08:00 via iPhone
    推广文写的烂,内容也差劲。不如散播焦虑来的流量多
    wdssmq
        13
    wdssmq  
       2021-05-06 14:38:31 +08:00
    挪到推广节点吧。。所以说,用微信公众号分享代码的真的叫码农么???
    ezshine
        14
    ezshine  
    OP
       2021-05-06 15:41:25 +08:00
    @belin520 说得好,下次还是散播焦虑吧
    ezshine
        15
    ezshine  
    OP
       2021-05-06 15:41:54 +08:00
    @sheeta
    @domodomo 哈哈,欢迎吐槽
    ezshine
        16
    ezshine  
    OP
       2021-05-06 15:43:34 +08:00
    @wdssmq 不引流,我用爱浇花吗?哈哈
    wudizaliangbing
        17
    wudizaliangbing  
       2021-05-06 16:28:34 +08:00
    答应我,不要做舔狗
    a4854857
        18
    a4854857  
       2021-05-06 16:51:19 +08:00
    总所周知.v2 天生反推广..特别是公众号之类的..商家抽奖另说.
    wdssmq
        19
    wdssmq  
       2021-05-06 17:16:46 +08:00
    说起来我好像去年才弄微信公众号:
    水水不想说
    因为我真的不知道要在上边发什么,,自己的博客不好么,还能直接 md 写。。
    pabupa
        20
    pabupa  
       2021-05-06 17:27:19 +08:00
    脑瘫……
    pabupa
        21
    pabupa  
       2021-05-06 17:30:08 +08:00
    @pabupa 对不起,不该骂人的……我给你点个感谢吧……不好意思
    ezshine
        22
    ezshine  
    OP
       2021-05-06 17:37:53 +08:00
    @a4854857 嗯,可以理解,但是 V2 对内容作者的机制是不友好的。如果不引流,为什么要来 V2 发文章呢?代码发到公众号是为了关注,发到 github 难道不是为了 star,这有什么区别。
    ezshine
        23
    ezshine  
    OP
       2021-05-06 17:39:50 +08:00
    @wdssmq 看来你很久不发公众号了,现在的工具很厉害。我的公众号也全都是 md 写的,然后掘金,V2,知乎都复制粘贴一份就行。核心还是想把粉丝沉淀到 B 站和公众号里,V2 的机制对内容作者并不太好,不引流,在这发文的意义不大。
    ezshine
        24
    ezshine  
    OP
       2021-05-06 17:40:19 +08:00
    @pabupa 哈哈,收到
    HankAviator
        25
    HankAviator  
       2021-05-06 20:57:25 +08:00
    这分享太费小姐姐了
    看着自己的名字在一片漆黑(是什么场合我们要用黑底呢)中炸裂,然后慢慢消失总感觉毛骨悚然。不过效果倒是挺好看的。
    iloveayu
        26
    iloveayu  
       2021-05-06 23:08:24 +08:00
    你说的这个小阿姨是不是你自己
    root01
        27
    root01  
       2021-05-07 08:58:59 +08:00
    磨磨唧唧,要想分享就别引流
    Vitta
        28
    Vitta  
       2021-05-07 12:59:14 +08:00
    很好啊
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4122 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 05:27 PVG 13:27 LAX 21:27 JFK 00:27
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86