资讯专栏INFORMATION COLUMN

十分钟实现灭霸打响指灰飞烟灭的效果

Wildcard / 1845人阅读

摘要:全部文章列表从模块化到私有仓库搭建十分钟实现灭霸打响指灰飞烟灭的效果是时候开发你自己的扩展插件了

看过复仇者联盟的都知道,灭霸作为计划生育政策的坚定支持者和执行者,一个响指清除了宇宙中二分之一的生命。电影中被清除的生命灰飞烟灭的镜头很是酷炫,所以在复联4上映后,那个不存在的网站google,推出了一个彩蛋,如果在搜索框搜索灭霸,会出现一个手套的按钮,点击后会让网页搜索结果消失一半。

恩~这很谷歌。
效果虽然酷炫但其实并不复杂,这里带着大家一起来实现一下,网上也已经有了一些教程(Thanos Snap Effect JavaScript Tutorial),这里稍微加点东西,灭霸的响指毕竟是真的打而不是用鼠标点按钮,所以我会加上音量检测,当检测到响指的声音(其实是超过某个音量预值)就触发效果,然后就可以愉快的向朋友装逼了。

源代码地址 准备开始

我们这里只用一个图片元素,HTML结构如下

<body>
     <div class="content">
            <div id="image">
                
                <img
                    src="https://i.loli.net/2019/05/06/5ccffa469ec52.jpg"
                    width="400"
                />
            div>
    div>
body>
动画的实现

    将html转成canvas,为后面处理做准备。这里我们使用html2canvas库,可以将html中的dom节点绘制成canvas,相当于对这个dom节点进行截图,使用很简单,代码如下(网页生成海报图片就可以用这个库来做)。

const imageBox = document.querySelector("#image")
html2canvas(imageBox, {
    backgroundColor: "transparent" //背景设置为透明
}).then(canvas=>{
    //处理canvas的代码(注意.then这种写法只有在新版本的html2canvas可用)
});

    这里我们拿到了包含了图片信息的canvas后,要通过canvas的getImageData来获取到canvas画布上的每个像素的信息。

 //处理canvas的代码
const ctx = canvas.getContext("2d");
const imageData = ctx.getImageData(
    0,
    0,
    canvas.width,
    canvas.height
);
const pixelArr = imageData.data; //像素信息

图像信息被存储在一个Uint8ClampedArray(8位无符号整型固定数组)中,这个数组中的值为0到255的整数,按图片中像素从左到右从上到下的顺序,每4个数字表示一个像素信息,这4个数字分别表示rgba(r-红色,g-绿,b-蓝色,a-透明度)的四个值。 比如这样一个图片

它的像素信息即为

[0,0,0,255,255,255,255,255,255,0,0,255,0,255,0,255]

    接下来是最关键的一步,创建多个同等长度的数组,填充上透明像素信息(数组中的值全是0即可),然后将之前拿到的图像像素信息“随机”分布到这些数组中,这些数组就包含了原图像的部分内容,原教程里面用到了一个随机数生成的库chance来控制随机数出现概率,直接使用完全随机数也没有问题。

//创建一个和图像信息数组长度相同的数组并填充0(相当于一个和原图像尺寸相同的透明图像)
const data = pixelArr.slice(0).fill(0); 
//创建透明图像数组的个数,不能太小也不能太大。
const canvasCount = 30;
//将透明图像数组复制多个
const imageDataArray = Array.from({ length: canvasCount }, () =>
    data.slice(0)
);
//将原图像上的像素信息随机分配进不同的透明图象上,位置保持不变
for (let i = 0; i < pixelArr.length; i += 4) {
    const p = Math.floor((i / pixelArr.length) * canvasCount);
    //a为随机选出要放入像素信息的数组
    const a = imageDataArray[Math.floor(Math.random() * canvasCount];
    //将像素信息放入随机到的透明图像数组中覆盖
    a[i] = pixelArr[i];
    a[i + 1] = pixelArr[i + 1];
    a[i + 2] = pixelArr[i + 2];
    a[i + 3] = pixelArr[i + 3];
}

当canvasCount为3时效果如下:
原始图片canvas

生成的包含原图部分像素的3个canvas



canvasCount越大,生成的canvas越多,分配到每个canvas上面的像素就越少,飘的就越散。
4. 接下来就非常简单了,隐藏掉原始图像,为生成的canvas添加飘散动画就可以了,飘散动画主要组成就是高斯模糊,位移,旋转,透明度变化,具体代码这里就不写了,可以在demo源代码中看到,最终效果如下。

响指触发

灰飞烟灭的动画已经完成,接下来是如何触发这段动画,文章开始就说过谷歌搜索上的原始效果是通过点击按钮触发,而我们通过麦克风实时检测输入音量,当打响指时(音量达到一定大小)触发动画。

    首先要确保你的设备有麦克风等声音输入装置,然后监测并获取设备,如果有麦克风设备,网页上会弹出授权提示。

if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        // 获取用户的 media 信息
        navigator.mediaDevices
            .getUserMedia({ audio: true })
            .then(stream => {
                //音频处理代码
            })
            .catch(error => {
                mystatus.innerHTML = "获取音频时好像出了点问题。" + error;
            });
} else {
        mystatus.innerHTML = "不支持获取媒体接口";
}           

    音频处理代码

// 当输入音量超过此值时,表示检测大音量输入(响指声)
const TRIGGER_VALUE = 0.9; 
// 将麦克风的声音输入这个对象
mediaStreamSource = audioContext.createMediaStreamSource(
    stream
);
// 创建一个音频分析对象,采样的缓冲区大小为4096,输入和输出都是单声道
scriptProcessor = audioContext.createScriptProcessor(
    4096,
    1,
    1
);
// 将该分析对象与麦克风音频进行连接
mediaStreamSource.connect(scriptProcessor);
// 此举无甚效果,仅仅是因为解决 Chrome 自身的 bug
scriptProcessor.connect(audioContext.destination);

// 开始处理音频
scriptProcessor.onaudioprocess = function(e) {
    // 获得缓冲区的输入音频,转换为包含了PCM通道数据的32位浮点数组
    let buffer = e.inputBuffer.getChannelData(0);
    // 获取缓冲区中最大的音量值
    let maxVal = Math.max.apply(Math, buffer);
    // 显示音量值
    if (maxVal > TRIGGER_VALUE) {
        //灰飞烟灭动画
        start(); 
    }
};
最后

一切搞定,就这么简单可以拿去装逼了,不过我同事问我,只能监测音量大小吗,这样的话不管是咳嗽声,大喊一声,啪啪啪声都可以触发,能不能真的只检测响指的声音。 嗯~这是个好问题,大家一起想想吧。

全部文章列表

从模块化到NPM私有仓库搭建

十分钟实现灭霸打响指灰飞烟灭的效果

是时候开发你自己的vscode扩展插件了

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/6807.html

相关文章

  • 尝试用 vue 实现霸打响指英雄消失效果 demo

    摘要:写在前面灭霸打响指的消失效果。算是蹭热度的一个我通过试图去查看是如何实现的,也抠了一些音频图片资源下来。点击一下手套,伴随音效和响指的动画,会有一半的英雄消失。翻转时间,英雄又回来的效果是将原来的节点设置为可见的,并加了回复动画。 写在前面 灭霸打响指的消失效果。效果来源于 Google 搜索灭霸 或者 thanos。算是蹭热度的一个 Feature, 我通过 F12 试图去查看是如何实现的...

    kelvinlee 评论0 收藏0
  • 关于Vue2一些值得推荐文章 -- 五、六月份

    摘要:五六月份推荐集合查看最新的请点击集前端最近很火的框架资源定时更新,欢迎一下。苏幕遮燎沈香宋周邦彦燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。叶上初阳乾宿雨,水面清圆,一一风荷举。家住吴门,久作长安旅。五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 五、六月份推荐集合 查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏...

    Terry_Tai 评论0 收藏0
  • 关于Vue2一些值得推荐文章 -- 五、六月份

    摘要:五六月份推荐集合查看最新的请点击集前端最近很火的框架资源定时更新,欢迎一下。苏幕遮燎沈香宋周邦彦燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。叶上初阳乾宿雨,水面清圆,一一风荷举。家住吴门,久作长安旅。五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 五、六月份推荐集合 查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏...

    sutaking 评论0 收藏0
  • 关于Vue2一些值得推荐文章 -- 五、六月份

    摘要:五六月份推荐集合查看最新的请点击集前端最近很火的框架资源定时更新,欢迎一下。苏幕遮燎沈香宋周邦彦燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。叶上初阳乾宿雨,水面清圆,一一风荷举。家住吴门,久作长安旅。五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 五、六月份推荐集合 查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏...

    khs1994 评论0 收藏0
  • 灭霸无限手套说起

    摘要:前两天看到搜索有个彩蛋,搜索灭霸或者,点击右边的无限手套触发彩蛋,打个响指,消灭一半的搜索结果条目,消失特效类似电影里的。但是百度的这个页面样式类是动态的,还要把整个内容也输出,而且很多图片大概是经过了什么处理,没权限显示不了,遂放弃。 本文不是技术文章,只是单纯记录下 最近妇联4在热映,先剧透两个精彩片段。showImg(https://segmentfault.com/img/bV...

    whatsns 评论0 收藏0

发表评论

0条评论

Wildcard

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<