說到防抖,想必多數(shù)人首先想到的是相機的防抖。因為我們并不是機器人,所以拿手機拍照的時候,手都會有不易察覺的抖動,這樣的抖動會影響相片的質(zhì)量。手機對這些情況做的一些補償操作,減小了手抖對成像造成的影響。
我們都知道,JavaScript 是一門編程語言,不是人類也不是機器人。那什么情況下,會產(chǎn)生“抖動”呢?
聯(lián)想一個平平無奇的登錄框,當(dāng)用戶信息輸入完畢,點擊登錄按鈕,可能網(wǎng)速有點慢還是啥的,用戶等得不耐煩,不停點擊,導(dǎo)致鼠標(biāo)患上帕金森,登錄按鈕就被一次一次地點擊,前端不停地向后臺發(fā)送重復(fù)的請求。
如下面的例子(這里點擊一次,執(zhí)行 console.log('click'), 并且用 console.log('submit') 代指請求):
可以看到,短時間內(nèi)連續(xù)點擊,每次點擊都會觸發(fā)請求.
這種情況,就屬于“抖動”。
服務(wù)器接收到這樣的請求,肯定是一臉懵啊,這誰頂?shù)米。?/p>
這個時候,就需要像手機相機一樣,做一些操作,減少鼠標(biāo)抖動對網(wǎng)絡(luò)請求的影響,減輕服務(wù)器的壓力。
“抖動”情景下,多次點擊,導(dǎo)致發(fā)送了多次一樣的請求。函數(shù)防抖的處理方式是:先規(guī)定一個時間段,比如一秒,點擊按鈕,一秒之后再發(fā)送請求,假如一秒內(nèi)又產(chǎn)生了一次點擊,那么重新計時,點擊過后一秒再發(fā)送請求。
這樣一來,規(guī)定時間段內(nèi)的快速點擊,只會產(chǎn)生一次請求。不管打字多快的手速,也戰(zhàn)勝不了防抖的函數(shù)。
直接上代碼:
const debounce=(func, delay=200)=> { let timeout=null return function () { clearTimeout(timeout) timeout=setTimeout(()=> { func.apply(this, arguments) }, delay) } }
debounce 函數(shù)接受一個函數(shù) func 和一個默認為 200 毫秒延遲時間 delay 作為參數(shù)。返回一個函數(shù),觸發(fā)返回的函數(shù),開始計時,delay 毫秒后觸發(fā) func, 假如 delay 時間段內(nèi),再次觸發(fā)這個函數(shù),那么重新計時,delay 毫秒后觸發(fā) func.
debounce 首先聲明變量 timeout, 用于存放之后 setTimeout 函數(shù)返回的定時器編號。
然后返回一個函數(shù),函數(shù)內(nèi)執(zhí)行 clearTimeout 來依據(jù)先前聲明的 timeout 來清除定時器。當(dāng)然,一開始,傳入的 timeout 值為 null, 這時的清除操作忽略不計。
接著,執(zhí)行 setTimeout, 在至少 delay 規(guī)定的毫秒后,將 setTimeout 的回調(diào)函數(shù)添加到當(dāng)前事件隊列,回調(diào)內(nèi)執(zhí)行 func 函數(shù)。并且把返回的定時器編號賦值給 timeout , 這樣,下一次觸發(fā) debounce 返回的函數(shù)時,就可以清除通過上面的 clearTimeout(timeout) 來清除定時器 。
注意到上面執(zhí)行 func 用的是 func.apply(this, arguments), 這樣一來,就可以對 debounce 返回的那個函數(shù)傳遞參數(shù),func 執(zhí)行的時候,再把參數(shù)傳給 func.
來用一下:
const submit=()=> { console.log('submit') } const debounceSubmit=debounce(submit, 500) let btnSubmit=document.getElementById('submit') btnSubmit.addEventListener('click', ()=> { console.log('click') debounceSubmit() })
這里將 submit 函數(shù)傳入 debounce 函數(shù),并設(shè)置延遲時間為 500 毫秒。 debounce 返回的函數(shù)賦給 debounceSubmit , 然后在提交按鈕 btnSubmit 的點擊事件回調(diào)中執(zhí)行 debounceSubmit.
看下效果:
上圖中,一開始的幾次連續(xù)點擊,都不會觸發(fā) submit ,停止點擊后,才觸發(fā)了一次 submit . 之后兩次有一定間隔時間的點擊,都觸發(fā)了 submit.
函數(shù)的防抖將一定時間內(nèi)的多次操作,減少為一次,去除冗余,節(jié)約資源。
去,當(dāng)我們面對交通違法記分時,往往感到頭疼和無奈。不僅是因為扣分帶來的經(jīng)濟和時間成本,更是因為缺乏一個系統(tǒng)、便捷的方式來學(xué)習(xí)和了解交通規(guī)則,從而避免再次犯錯。然而,現(xiàn)在有了學(xué)法減分工具,這一切都變得簡單而高效。
這是微信公眾號
一款專為駕駛員打造的交通安全學(xué)習(xí)減分題庫,通過減分俠隨時在線刷題練習(xí),涵蓋豐富的交通安全知識,讓學(xué)習(xí)減分更輕松!
下方附上一些測試的試題及答案
1、【35】
A.other B.big C.little D.robot
答案:C
2、“足智多謀、隨機應(yīng)變”是思維的哪種品質(zhì)?()
A.廣闊性 B.獨立性 C.靈活性 D.邏輯性
答案:C
3、【C20】
A.formed B.caused C.made D.fallen
答案:A
4、機上遇到特別肥胖的旅客時,乘務(wù)員要主動為該旅客提供____________________。
答案:加長安全帶
5、下列哪項不是蘇聯(lián)“休克療法”的內(nèi)容?()
A.快速私有化 B.自由化 C.穩(wěn)定化 D.擴張性財政政策
答案:D
6、【31】
A.keeps B.draws C.inclines D.tends
答案:B
7、Which of the following statements is true?
A.Five percent of Americans are very unhappy. B.Over fifty percent of Americans are very happy. C.Twenty percent of Americans are very unhappy. D.Sixty to seventy percent of Americans are not happy.
答案:A
8、嵐山は日本の___にあります()
A、東京 B、京都 C、奈良
答案:B
9、【C11】
A.hot-sold B.good-sold C.hot-selling D.good-selling
答案:C
10、【36】
A.similarly B.greatly C.hardly D.clearly
答案:C
11、產(chǎn)業(yè)結(jié)構(gòu)理論是關(guān)于產(chǎn)業(yè)內(nèi)企業(yè)結(jié)構(gòu)的理論。
對 錯
答案:錯
12、【單選題】下列保險項目中只由用人單位繳納保險費的是() 答案:工傷保險
答案:工傷保險
13、【C9】
A.And B.While C.But D.Nevertheless
答案:A
14、【31】
A.some one B.one C.he D.reader
答案:B
15、【29】
A.fabulous B.frigid C.feeble D.fashionable
答案:D
coursera是面向大學(xué)生的免費在線學(xué)習(xí)APP
它與全世界最頂尖的大學(xué)和機構(gòu)合作,提供任何人可學(xué)習(xí)的在線課程。
這是一個網(wǎng)站
:題庫全面,包含公職、消防、煤礦、國網(wǎng)、醫(yī)學(xué)等行業(yè)題目。支持拍照、讀屏搜題。簡單易用、一鍵開始、快速響應(yīng)!
以番茄工作法為基礎(chǔ)的時間管理,科學(xué)方便。開啟學(xué)霸模式可以讓我們專注于自己做的事情,避免其他娛樂軟件的打擾。
這是一款提升我們的自律和專注度用的APP。
這是一個網(wǎng)站
涵蓋初高中/大學(xué)/專升本/考研/成人自考/各類資格證等等考試題目,同時支持截圖搜題、語音搜題,里面還有1000+考試題庫可以練習(xí)
中國大學(xué)MOOC(慕課) 是國內(nèi)優(yōu)質(zhì)的中文MOOC學(xué)習(xí)平臺
由愛課程網(wǎng)攜手網(wǎng)易云課堂打造。平臺擁有包括985高校在內(nèi)提供的千余門課程,其中首批獲得認定的國家精品在線開放課程322門
菜鳥教程是一個完全免費的編程學(xué)習(xí)軟件。
它免費提供了HTML / CSS 、JavaScript 、服務(wù)端、移動端、XML 教程、http://ASP.NET 、Web Service 、開發(fā)工具、網(wǎng)站建設(shè);每類教程還細分了很多種不同的教程,例如服務(wù)端學(xué)習(xí)教程包括:PHP 教程、Python 基礎(chǔ)教程、Python 3 教程、Linux 教程、Java 教程、Ruby 教程、C 語言教程、C++ 教程、Go 語言教程、正則表達式等豐富的編程學(xué)習(xí)教程
這是個微信公眾號
搜索的題目全部都有詳細的提示,以及中間做題步驟、解決方法,你可以導(dǎo)入照片或拍照的方式輸入數(shù)學(xué)問題,它還支持將重點題目進行收集整理,非常方便大家用來復(fù)習(xí)。
微信讀書是騰訊官方出品的一款在線小說閱讀APP,它的書庫儲量非常豐富,我們可以直接通過搜索獲取到想要閱讀的書籍,喜歡閱讀古今中外名著書籍的小伙伴值得嘗試。
我們可以將想要閱讀的書籍加入書架,還能夠設(shè)置虛擬書架,這樣你的好友就不知道你在讀什么書了。
祝愿每一位大學(xué)生都能夠充分利用這些日常學(xué)習(xí)工具,成為自己學(xué)業(yè)道路上的強者。
近刷臉支付很火,老板們當(dāng)然要追趕時代潮流,于是就有了刷臉支付這個項目。前端實現(xiàn)關(guān)鍵的技術(shù)是攝像頭錄像,拍照和人臉比對,本文來探討一下如何在html5環(huán)境中如何實現(xiàn)刷臉支付以及開發(fā)過程中遇到的問題。
html5中獲取手機上的圖片,有兩種方式,使用input,如下可以打開攝像頭拍照:
<input type="file" capture="camera" accept="image/*"/>
另外如果想打開相冊,可以這樣:
<input type="file" accept="img/*">
但是這兩種方式都會有兼容性問題,用過的同學(xué)可能都知道。
getUserMedia是html5一個新的api,官方一點的定義是:
MediaDevices.getUserMedia() 會提示用戶給予使用媒體輸入的許可,媒體輸入會產(chǎn)生一個MediaStream,里面包含了請求的媒體類型的軌道。此流可以包含一個視頻軌道(來自硬件或者虛擬視頻源,比如相機、視頻采集設(shè)備和屏幕共享服務(wù)等等)、一個音頻軌道(同樣來自硬件或虛擬音頻源,比如麥克風(fēng)、A/D轉(zhuǎn)換器等等),也可能是其它軌道類型。
簡單一點說就是可以獲取到用戶攝像頭。
同上面input一樣,這種方式也有兼容性問題,不過可以使用其他方式解決,這里可以參考MediaDevices.getUserMedia(),文檔中有介紹"在舊的瀏覽器中使用新的API"。我這里在網(wǎng)上也找了一些參考,總結(jié)出一個相對全面的getUserMedia版本,代碼如下:
// 訪問用戶媒體設(shè)備
getUserMedia(constrains, success, error) {
if (navigator.mediaDevices.getUserMedia) {
//最新標(biāo)準(zhǔn)API
navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error);
} else if (navigator.webkitGetUserMedia) {
//webkit內(nèi)核瀏覽器
navigator.webkitGetUserMedia(constrains).then(success).catch(error);
} else if (navigator.mozGetUserMedia) {
//Firefox瀏覽器
navagator.mozGetUserMedia(constrains).then(success).catch(error);
} else if (navigator.getUserMedia) {
//舊版API
navigator.getUserMedia(constrains).then(success).catch(error);
} else {
this.scanTip="你的瀏覽器不支持訪問用戶媒體設(shè)備"
}
}
獲取設(shè)備方法有兩個回調(diào)函數(shù),一個是成功,一個是失敗。成功了就開始播放視頻,播放視屏其實就是給video設(shè)置一個url,并調(diào)用play方法,這里設(shè)置url要考慮不同瀏覽器兼容性,代碼如下:
success(stream) {
this.streamIns=stream
// 設(shè)置播放地址,webkit內(nèi)核瀏覽器
this.URL=window.URL || window.webkitURL
if ("srcObject" in this.$refs.refVideo) {
this.$refs.refVideo.srcObject=stream
} else {
this.$refs.refVideo.src=this.URL.createObjectURL(stream)
}
this.$refs.refVideo.onloadedmetadata=e=> {
// 播放視頻
this.$refs.refVideo.play()
this.initTracker()
}
},
error(e) {
this.scanTip="訪問用戶媒體失敗" + e.name + "," + e.message
}
注意:
視屏在video中播放成功之后就開始識別人臉了,這里使用到一個第三方的功能tracking.js,是國外的大神寫的JavaScript圖像識別插件。關(guān)鍵代碼如下:
// 人臉捕捉
initTracker() {
this.context=this.$refs.refCanvas.getContext("2d") // 畫布
this.tracker=new tracking.ObjectTracker(['face']) // tracker實例
this.tracker.setStepSize(1.7) // 設(shè)置步長
this.tracker.on('track', this.handleTracked) // 綁定監(jiān)聽方法
try {
tracking.track('#video', this.tracker) // 開始追蹤
} catch (e) {
this.scanTip="訪問用戶媒體失敗,請重試"
}
}
捕獲到人臉之后,可以在頁面上用一個小方框標(biāo)注出來,這樣有點交互效果。
// 追蹤事件
handleTracked(e) {
if (e.data.length===0) {
this.scanTip='未檢測到人臉'
} else {
if (!this.tipFlag) {
this.scanTip='檢測成功,正在拍照,請保持不動2秒'
}
// 1秒后拍照,僅拍一次
if (!this.flag) {
this.scanTip='拍照中...'
this.flag=true
this.removePhotoID=setTimeout(()=> {
this.tackPhoto()
this.tipFlag=true
}, 2000)
}
e.data.forEach(this.plot)
}
}
在頁面中畫一些方框,標(biāo)識出人臉:
<div class="rect" v-for="item in profile"
:style="{ width: item.width + 'px', height: item.height + 'px', left: item.left + 'px', top: item.top + 'px'}"></div>
// 繪制跟蹤框
plot({x, y, width: w, height: h}) {
// 創(chuàng)建框?qū)ο?
this.profile.push({ width: w, height: h, left: x, top: y })
}
拍照,就是使用video作為圖片源,在canvas中保存一張圖片下來,注意這里使用toDataURL方法的時候可以設(shè)置第二個參數(shù)quality,從0到1,0表示圖片比較粗糙,但是文件比較小,1表示品質(zhì)最好。
// 拍照
tackPhoto() {
this.context.drawImage(this.$refs.refVideo, 0, 0, this.screenSize.width, this.screenSize.height)
// 保存為base64格式
this.imgUrl=this.saveAsPNG(this.$refs.refCanvas)
// this.compare(imgUrl)
this.close()
},
// Base64轉(zhuǎn)文件
getBlobBydataURI(dataURI, type) {
var binary=window.atob(dataURI.split(',')[1]);
var array=[];
for(var i=0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {
type: type
});
},
// 保存為png,base64格式圖片
saveAsPNG(c) {
return c.toDataURL('image/png', 0.3)
}
拍照完成之后就可以把文件發(fā)送給后端,讓后端進行對比驗證,這里后端使用的是阿里云的接口。
最后,demo我已經(jīng)放在github上了,感興趣可以打開看一下。
效果如下:
最后放在項目中,無非就是最后一個步驟,去調(diào)用接口比對,根據(jù)比對結(jié)果成功是成功還是失敗,決定是人臉支付還是繼續(xù)使用原來的密碼支付,效果如下:
ps:這里人臉比對失敗了,是因為我?guī)е谡郑筒贿谘缆赌樍恕?/p>
作者:Tyler Ning 出處:http://www.cnblogs.com/tylerdonet/ 本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,如有問題,可以通過以下郵箱地址344805262@qq.com 聯(lián)系我,非常感謝。
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。