摘要:全部文章列表從模塊化到私有倉(cāng)庫(kù)搭建十分鐘實(shí)現(xiàn)滅霸打響指灰飛煙滅的效果是時(shí)候開(kāi)發(fā)你自己的擴(kuò)展插件了
看過(guò)復(fù)仇者聯(lián)盟的都知道,滅霸作為計(jì)劃生育政策的堅(jiān)定支持者和執(zhí)行者,一個(gè)響指清除了宇宙中二分之一的生命。電影中被清除的生命灰飛煙滅的鏡頭很是酷炫,所以在復(fù)聯(lián)4上映后,那個(gè)不存在的網(wǎng)站google,推出了一個(gè)彩蛋,如果在搜索框搜索滅霸,會(huì)出現(xiàn)一個(gè)手套的按鈕,點(diǎn)擊后會(huì)讓網(wǎng)頁(yè)搜索結(jié)果消失一半。
源代碼地址 準(zhǔn)備開(kāi)始
我們這里只用一個(gè)圖片元素,HTML結(jié)構(gòu)如下
<body>
<div class="content">
<div id="image">
<img
src="https://i.loli.net/2019/05/06/5ccffa469ec52.jpg"
width="400"
/>
div>
div>
body>
動(dòng)畫(huà)的實(shí)現(xiàn)
將html轉(zhuǎn)成canvas,為后面處理做準(zhǔn)備。這里我們使用html2canvas庫(kù),可以將html中的dom節(jié)點(diǎn)繪制成canvas,相當(dāng)于對(duì)這個(gè)dom節(jié)點(diǎn)進(jìn)行截圖,使用很簡(jiǎn)單,代碼如下(網(wǎng)頁(yè)生成海報(bào)圖片就可以用這個(gè)庫(kù)來(lái)做)。
const imageBox = document.querySelector("#image")
html2canvas(imageBox, {
backgroundColor: "transparent" //背景設(shè)置為透明
}).then(canvas=>{
//處理canvas的代碼(注意.then這種寫(xiě)法只有在新版本的html2canvas可用)
});
這里我們拿到了包含了圖片信息的canvas后,要通過(guò)canvas的getImageData來(lái)獲取到canvas畫(huà)布上的每個(gè)像素的信息。
//處理canvas的代碼
const ctx = canvas.getContext("2d");
const imageData = ctx.getImageData(
0,
0,
canvas.width,
canvas.height
);
const pixelArr = imageData.data; //像素信息
圖像信息被存儲(chǔ)在一個(gè)Uint8ClampedArray(8位無(wú)符號(hào)整型固定數(shù)組)中,這個(gè)數(shù)組中的值為0到255的整數(shù),按圖片中像素從左到右從上到下的順序,每4個(gè)數(shù)字表示一個(gè)像素信息,這4個(gè)數(shù)字分別表示rgba(r-紅色,g-綠,b-藍(lán)色,a-透明度)的四個(gè)值。 比如這樣一個(gè)圖片
[0,0,0,255,255,255,255,255,255,0,0,255,0,255,0,255]
接下來(lái)是最關(guān)鍵的一步,創(chuàng)建多個(gè)同等長(zhǎng)度的數(shù)組,填充上透明像素信息(數(shù)組中的值全是0即可),然后將之前拿到的圖像像素信息“隨機(jī)”分布到這些數(shù)組中,這些數(shù)組就包含了原圖像的部分內(nèi)容,原教程里面用到了一個(gè)隨機(jī)數(shù)生成的庫(kù)chance來(lái)控制隨機(jī)數(shù)出現(xiàn)概率,直接使用完全隨機(jī)數(shù)也沒(méi)有問(wèn)題。
//創(chuàng)建一個(gè)和圖像信息數(shù)組長(zhǎng)度相同的數(shù)組并填充0(相當(dāng)于一個(gè)和原圖像尺寸相同的透明圖像)
const data = pixelArr.slice(0).fill(0);
//創(chuàng)建透明圖像數(shù)組的個(gè)數(shù),不能太小也不能太大。
const canvasCount = 30;
//將透明圖像數(shù)組復(fù)制多個(gè)
const imageDataArray = Array.from({ length: canvasCount }, () =>
data.slice(0)
);
//將原圖像上的像素信息隨機(jī)分配進(jìn)不同的透明圖象上,位置保持不變
for (let i = 0; i < pixelArr.length; i += 4) {
const p = Math.floor((i / pixelArr.length) * canvasCount);
//a為隨機(jī)選出要放入像素信息的數(shù)組
const a = imageDataArray[Math.floor(Math.random() * canvasCount];
//將像素信息放入隨機(jī)到的透明圖像數(shù)組中覆蓋
a[i] = pixelArr[i];
a[i + 1] = pixelArr[i + 1];
a[i + 2] = pixelArr[i + 2];
a[i + 3] = pixelArr[i + 3];
}
當(dāng)canvasCount為3時(shí)效果如下:
原始圖片canvas
生成的包含原圖部分像素的3個(gè)canvas
canvasCount越大,生成的canvas越多,分配到每個(gè)canvas上面的像素就越少,飄的就越散。
4. 接下來(lái)就非常簡(jiǎn)單了,隱藏掉原始圖像,為生成的canvas添加飄散動(dòng)畫(huà)就可以了,飄散動(dòng)畫(huà)主要組成就是高斯模糊,位移,旋轉(zhuǎn),透明度變化,具體代碼這里就不寫(xiě)了,可以在demo源代碼中看到,最終效果如下。
響指觸發(fā)
灰飛煙滅的動(dòng)畫(huà)已經(jīng)完成,接下來(lái)是如何觸發(fā)這段動(dòng)畫(huà),文章開(kāi)始就說(shuō)過(guò)谷歌搜索上的原始效果是通過(guò)點(diǎn)擊按鈕觸發(fā),而我們通過(guò)麥克風(fēng)實(shí)時(shí)檢測(cè)輸入音量,當(dāng)打響指時(shí)(音量達(dá)到一定大?。┯|發(fā)動(dòng)畫(huà)。
首先要確保你的設(shè)備有麥克風(fēng)等聲音輸入裝置,然后監(jiān)測(cè)并獲取設(shè)備,如果有麥克風(fēng)設(shè)備,網(wǎng)頁(yè)上會(huì)彈出授權(quán)提示。
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
// 獲取用戶的 media 信息
navigator.mediaDevices
.getUserMedia({ audio: true })
.then(stream => {
//音頻處理代碼
})
.catch(error => {
mystatus.innerHTML = "獲取音頻時(shí)好像出了點(diǎn)問(wèn)題。" + error;
});
} else {
mystatus.innerHTML = "不支持獲取媒體接口";
}
音頻處理代碼
// 當(dāng)輸入音量超過(guò)此值時(shí),表示檢測(cè)大音量輸入(響指聲)
const TRIGGER_VALUE = 0.9;
// 將麥克風(fēng)的聲音輸入這個(gè)對(duì)象
mediaStreamSource = audioContext.createMediaStreamSource(
stream
);
// 創(chuàng)建一個(gè)音頻分析對(duì)象,采樣的緩沖區(qū)大小為4096,輸入和輸出都是單聲道
scriptProcessor = audioContext.createScriptProcessor(
4096,
1,
1
);
// 將該分析對(duì)象與麥克風(fēng)音頻進(jìn)行連接
mediaStreamSource.connect(scriptProcessor);
// 此舉無(wú)甚效果,僅僅是因?yàn)榻鉀Q Chrome 自身的 bug
scriptProcessor.connect(audioContext.destination);
// 開(kāi)始處理音頻
scriptProcessor.onaudioprocess = function(e) {
// 獲得緩沖區(qū)的輸入音頻,轉(zhuǎn)換為包含了PCM通道數(shù)據(jù)的32位浮點(diǎn)數(shù)組
let buffer = e.inputBuffer.getChannelData(0);
// 獲取緩沖區(qū)中最大的音量值
let maxVal = Math.max.apply(Math, buffer);
// 顯示音量值
if (maxVal > TRIGGER_VALUE) {
//灰飛煙滅動(dòng)畫(huà)
start();
}
};
最后
一切搞定,就這么簡(jiǎn)單可以拿去裝逼了,不過(guò)我同事問(wèn)我,只能監(jiān)測(cè)音量大小嗎,這樣的話不管是咳嗽聲,大喊一聲,啪啪啪聲都可以觸發(fā),能不能真的只檢測(cè)響指的聲音。 嗯~這是個(gè)好問(wèn)題,大家一起想想吧。
全部文章列表從模塊化到NPM私有倉(cāng)庫(kù)搭建
十分鐘實(shí)現(xiàn)滅霸打響指灰飛煙滅的效果
是時(shí)候開(kāi)發(fā)你自己的vscode擴(kuò)展插件了
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/6807.html
摘要:寫(xiě)在前面滅霸打響指的消失效果。算是蹭熱度的一個(gè)我通過(guò)試圖去查看是如何實(shí)現(xiàn)的,也摳了一些音頻圖片資源下來(lái)。點(diǎn)擊一下手套,伴隨音效和響指的動(dòng)畫(huà),會(huì)有一半的英雄消失。翻轉(zhuǎn)時(shí)間,英雄又回來(lái)的效果是將原來(lái)的節(jié)點(diǎn)設(shè)置為可見(jiàn)的,并加了回復(fù)動(dòng)畫(huà)。 寫(xiě)在前面 滅霸打響指的消失效果。效果來(lái)源于 Google 搜索滅霸 或者 thanos。算是蹭熱度的一個(gè) Feature, 我通過(guò) F12 試圖去查看是如何實(shí)現(xiàn)的...
摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥(niǎo)雀呼晴,侵曉窺檐語(yǔ)。葉上初陽(yáng)乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門(mén),久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...
摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥(niǎo)雀呼晴,侵曉窺檐語(yǔ)。葉上初陽(yáng)乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門(mén),久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...
摘要:前兩天看到搜索有個(gè)彩蛋,搜索滅霸或者,點(diǎn)擊右邊的無(wú)限手套觸發(fā)彩蛋,打個(gè)響指,消滅一半的搜索結(jié)果條目,消失特效類(lèi)似電影里的。但是百度的這個(gè)頁(yè)面樣式類(lèi)是動(dòng)態(tài)的,還要把整個(gè)內(nèi)容也輸出,而且很多圖片大概是經(jīng)過(guò)了什么處理,沒(méi)權(quán)限顯示不了,遂放棄。 本文不是技術(shù)文章,只是單純記錄下 最近婦聯(lián)4在熱映,先劇透兩個(gè)精彩片段。showImg(https://segmentfault.com/img/bV...
閱讀 1729·2021-09-30 09:47
閱讀 3743·2021-09-22 15:05
閱讀 2941·2021-08-30 09:44
閱讀 3686·2019-08-30 15:55
閱讀 1452·2019-08-30 13:08
閱讀 1385·2019-08-29 16:40
閱讀 606·2019-08-29 12:45
閱讀 1443·2019-08-29 11:25