Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 国产成人精品.一二区,国产成人自拍在线,99在线视频观看

          整合營(yíng)銷(xiāo)服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢(xún)熱線:

          JavaScript - Fetch API 完全手冊(cè)

          果您想從 API 加載數(shù)據(jù),那么 fetch API 是在 JavaScript 中執(zhí)行此操作的最佳方式。您不需要引入任何第三方庫(kù),就可以直接使用方便的fetch。

          像上圖所示,絕大多數(shù)瀏覽器已經(jīng)原生支持Fetch,所以您可以放心使用。Node.js 對(duì)它的支持也正在路上,F(xiàn)etch 已經(jīng)作為 Node v17 中的實(shí)驗(yàn)性功能提供,你可以使用 node app.js --experimental-fetch 來(lái)開(kāi)啟它。

          Fetch API 的基本使用

          Fetch API 是基于Promise的,所以如果你不了解Promise, 最好先學(xué)習(xí)一下Promise。

          調(diào)用 fetch API 的最簡(jiǎn)單方法是將 URL 傳遞給 fetch 函數(shù)。

          這將返回一個(gè)包含響應(yīng)數(shù)據(jù)的Promise。此響應(yīng)數(shù)據(jù)包含狀態(tài)屬性以及將原始響應(yīng)數(shù)據(jù)轉(zhuǎn)換為 JSON、文本或其他格式的方法。

          上面顯示res.json() 是在我們的響應(yīng)中調(diào)用 json() 方法,這個(gè)方法會(huì)返回另外一個(gè) promise,該 promise 從我們的響應(yīng)中解析 JSON 數(shù)據(jù)。

          我們可以在后面的then方法中獲取到最終需要的JSON數(shù)據(jù)對(duì)象。

          如果您從 JSON api 獲取數(shù)據(jù),這就是大多數(shù)獲取請(qǐng)求的樣子。 我們首先獲取 URL,然后將響應(yīng)轉(zhuǎn)換為 JSON,最后使用最終 .then 中的數(shù)據(jù)。

          如果使用async/await語(yǔ)法,可能會(huì)更簡(jiǎn)單點(diǎn)。

          Fetch 參數(shù)

          這將涵蓋您的一些 fetch 用途,但通常您需要傳遞其他選項(xiàng)來(lái)進(jìn)行 fetch 配置。 fetch 函數(shù)采用第二個(gè)選項(xiàng)對(duì)象參數(shù),其中包含大量潛在選項(xiàng)。

          method

          最常用的選項(xiàng)是方法選項(xiàng)。 此選項(xiàng)允許您設(shè)置要使用的 HTTP 動(dòng)詞(GET、POST、PUT、DELETE 等)。

          body

          如果您正在修改方法,那么您可能需要將數(shù)據(jù)與您的請(qǐng)求一起傳遞。 這就是 body 選項(xiàng)的用武之地。body 不接受對(duì)象,因此如果您想將 JSON 傳遞給您的 API,您必須首先將其轉(zhuǎn)換為字符串。

          headers

          現(xiàn)在,執(zhí)行上述操作可能看起來(lái)像是將 JSON 傳遞給 API 所需要做的一切,但這實(shí)際上是行不通的。 原因是您需要設(shè)置正確的標(biāo)頭來(lái)告訴您的 API 您正在發(fā)送 JSON 信息。 此標(biāo)頭選項(xiàng)允許您設(shè)置所需的任何 HTTP 標(biāo)頭。

          上面這組代碼是將 JSON 傳遞給 API 所需要做的一切。

          signal

          最后一個(gè)要說(shuō)的的是信號(hào)選項(xiàng)。 這個(gè)選項(xiàng)接受一個(gè) AbortSignal,它可以用來(lái)中止一個(gè)獲取請(qǐng)求。

          正如您從代碼中看到的那樣,這比其他選項(xiàng)要復(fù)雜一些。 首先你必須創(chuàng)建一個(gè)新的 AbortController 這個(gè)控制器有一個(gè)信號(hào)屬性,這是你傳遞給signal選項(xiàng)的。 控制器還有一個(gè) abort 方法,當(dāng)調(diào)用該方法時(shí),將使用相關(guān)信號(hào)中止獲取請(qǐng)求。 這將導(dǎo)致 fetch Promise以 AbortError Reject異常。

          這些選項(xiàng)應(yīng)該是可以cover你90%左右的用例。具體還有其他一些不常用的可以去查看官網(wǎng)文檔。

          總結(jié):

          fetch API 是一個(gè)功能強(qiáng)大的工具,易于上手,它包含適用于每個(gè)可以想象的用例的許多高級(jí)選項(xiàng)。最重要的是,馬上node.js就可以原生支持它,邏輯可以前后端共享,豈不美哉!

          感謝閱讀!

          文介紹HTML5 <audio>音頻元素的屬性,方法,以及事件相關(guān)的API的基本使用。

          內(nèi)容有些多,完整閱讀需要點(diǎn)時(shí)間,但很實(shí)用,可以先馬后看。

          一、audio使用基本案例

          <audio controls>
           <source src="audiofile.mp3" type="audio/mpeg">
           <source src="audiofile.ogg" type="audio/ogg">
           <!-- 如果瀏覽器不支持,則會(huì)呈現(xiàn)下面內(nèi)容 -->
           <p>你的瀏覽器不支持HTML5音頻,你可以<a href="audiofile.mp3">下載</a>這個(gè)音頻文件。</p>
          </audio>
          

          上面做法是早些年HTML5 <audio>常用代碼,因?yàn)槟菚r(shí)候IE8還是大頭,各大瀏覽器對(duì)各類(lèi)音頻格式支持情況參差不齊,因此,才借助<source>元素同時(shí)引用多個(gè)不同格式的音頻文件,通過(guò)type屬性指定mime type避免重復(fù)加載情況出現(xiàn)。

          但是,如今已經(jīng)不需要這么麻煩了。我們直接下面這樣就可以了:

          <audio src="audiofile.mp3" controls></audio>
          

          音頻文件常見(jiàn)下面3種格式,.ogg, .wav和.mp3,其中,.ogg Safari瀏覽器不支持(目前版本13),IE到Edge16都不支持;.wav則是IE-IE11不支持;但是.mp3 IE9+都支持。因此,我們?nèi)绻幌肼闊苯右粋€(gè)MP3格式就好了,由于就一種文件格式,因此type屬性也可以不用設(shè)置。

          //zxx: 也可以使用MP4視頻文件,因?yàn)镸P4視頻也包含ACC編碼音頻,不過(guò)就是體積大了很多,不建議這么使用。

          <audio>元素IE9瀏覽器就開(kāi)始支持,現(xiàn)在00后都快20歲了,也不需要為低版本瀏覽器做降級(jí)適配了。因此,簡(jiǎn)簡(jiǎn)單單一個(gè)<audio>元素就可以了。

          二、Audio HTML屬性

          下面看下<audio>元素屬性相關(guān)的一些細(xì)節(jié)。

          autoplay

          <audio src="audiofile.mp3" autoplay></audio>
          

          autoplay是個(gè)布爾屬性值,表示聲音是否自動(dòng)播放,默認(rèn)不自動(dòng)播放。然而,隨著瀏覽器的發(fā)展,這個(gè)屬性變得限制越來(lái)越多。首先在移動(dòng)端,autoplay自動(dòng)播放已經(jīng)被禁止了,PC端也已經(jīng)禁止,18年的時(shí)候,Chrome這么做了,然后被很多開(kāi)發(fā)者抗議,后來(lái)又恢復(fù)autoplay(給大家緩沖時(shí)間),現(xiàn)在已經(jīng)Chrome又不支持自動(dòng)播放了。

          原因是網(wǎng)頁(yè)在沒(méi)有警告的情況下自發(fā)地發(fā)出聲音,可能會(huì)讓用戶(hù)不愉快,體驗(yàn)不太好。因此,瀏覽器通常只允許在特定情況下成功地進(jìn)行自動(dòng)播放。

          關(guān)于更深入的autoplay策略可以參見(jiàn)MDN上的這篇文檔。

          不過(guò)根據(jù)我自己的一些實(shí)踐,資源靜音或者視頻沒(méi)有聲音情況下,autoplay偶爾也是會(huì)執(zhí)行的,不過(guò)都是偶現(xiàn),觸發(fā)自動(dòng)播放原因不詳。

          loop

          <audio src="audiofile.mp3" loop></audio>
          

          loop是個(gè)布爾屬性值,表示聲音是否循環(huán)播放,默認(rèn)不循環(huán)播放。loop屬性適合用在可以不斷循環(huán)的bgm背景音樂(lè)上。loop屬性在各個(gè)平臺(tái),各個(gè)瀏覽器下的表現(xiàn)良好,大家可以放心使用。

          JS設(shè)置音頻循環(huán)播放可以:

          document.querySelector('audio').loop = true;
          

          muted

          示意:

          <audio src="audiofile.mp3" muted></audio>
          

          muted也是個(gè)布爾屬性值,表示音頻是否靜音,默認(rèn)不靜音播放。muted屬性在各個(gè)平臺(tái),各個(gè)瀏覽器下的表現(xiàn)良好,大家可以放心使用。

          JS設(shè)置音頻靜音可以:

          document.querySelector('audio').muted = true;
          

          preload

          示意:

          <audio src="audiofile.mp3" preload="auto"></audio>
          

          preload可以指定音頻的預(yù)加載策略,也就是在播放之前需要提前加載好音頻的哪些資源。支持下面3個(gè)屬性值:

          1. none:表示在點(diǎn)擊播放按鈕之前不加載任何信息。
          2. metadata: 下載音頻的meta信息,就是視頻長(zhǎng)度,類(lèi)型,還有作者(如果有)等信息。/li>
          3. auto: 會(huì)嘗試下載整個(gè)音頻,如今5G都快來(lái)了,流量已經(jīng)不值錢(qián)了,因此,我個(gè)人是更推薦使用auto的,體驗(yàn)更好一點(diǎn)。然后,通常瀏覽器自己也會(huì)優(yōu)化加載策略,不會(huì)所有音頻文件都加載下來(lái),只是會(huì)加載一部分,保證點(diǎn)擊播放按鈕的時(shí)候,可以立即播放。

          preload屬性在iOS Safari瀏覽器下是被禁止的(桌面端無(wú)此問(wèn)題),對(duì)于一些對(duì)音頻播放時(shí)間實(shí)際要求比較高的場(chǎng)合,會(huì)給我們開(kāi)發(fā)帶來(lái)困難。通常解決方法是,第一次觸摸的時(shí)候,音頻靜音,同時(shí)觸發(fā)音頻play()然后很快再pause(),此時(shí),可以有類(lèi)似preload的預(yù)加載行為。

          不過(guò),Safari以后可能會(huì)改變preload在移動(dòng)端的加載策略,因?yàn)樵酵罅髁吭讲恢靛X(qián),這種自以為是的優(yōu)化反而會(huì)成為一種桎梏。

          controls

          示意:

          <audio src="audiofile.mp3" controls></audio>
          

          controls是個(gè)布爾屬性值,表示聲音是否顯示音頻播放暫停等控制器,默認(rèn)是不顯示的。

          如果沒(méi)有設(shè)置controls屬性,整個(gè)音頻文件播放面板都是完全隱藏的;如果有設(shè)置,則UI可能類(lèi)似下面這張圖(Chrome PC,設(shè)置了靜音)。


          不同瀏覽器,以及不同版本瀏覽器,其UI都不一樣。如果是開(kāi)發(fā)to用戶(hù)側(cè)產(chǎn)品,需要自定義音頻播放器的UI,讓各個(gè)瀏覽器下長(zhǎng)相一致,大家可以去github上找找開(kāi)源的項(xiàng)目。

          src

          示意:

          <audio src="audiofile.mp3"></audio>
          

          src屬性表示音頻的文件地址。可以用在<audio>元素上,也可以用在<source>元素上。<audio>元素上只能一個(gè)音頻地址,使用<source>可以并列多個(gè)不同格式的音頻文件。

          type

          <audio src="audiofile.mp3" type="audio/mpeg"></audio>
          

          type屬性用來(lái)指定音頻文件的mime type類(lèi)型。雖然不加type類(lèi)型,瀏覽器也能正確播放音頻文件,但通常建議加上type屬性。當(dāng)然,如果src音頻格式不固定,則type屬性反而推薦不加,錯(cuò)誤的type不如沒(méi)有type。

          三、在JS中調(diào)用的audio屬性

          <audio>元素還有一些屬性只能通過(guò)JavaScript設(shè)置,假設(shè)有HTML如下:

          <audio id="myAudio" src="audiofile.mp3"></audio>
          

          則:

          currentTime

          currentTime是一個(gè)可讀兼可寫(xiě)的屬性,用來(lái)設(shè)置或獲取當(dāng)前已經(jīng)播放的時(shí)長(zhǎng),單位是秒。

          例如:

          // 獲取音頻已經(jīng)播放時(shí)長(zhǎng)
          var playedTime = myAudio.currentTime;
          

          如果音頻尚未開(kāi)始播放,則playedTime的返回值是0。

          我們也可以通過(guò)設(shè)置currentTime屬性值,讓我們的音頻定位到我們希望的時(shí)間點(diǎn)進(jìn)行播放,例如,從5秒那里開(kāi)始播放,則:

          // 跳到5秒那里
          myAudio.currentTime = 5;
          

          volume

          volume也是一個(gè)可讀兼可寫(xiě)的屬性,用來(lái)設(shè)置或獲取音頻的音量大小,范圍是0-1。

          例如,設(shè)置音量50%,則:

          // 設(shè)置音量50%
          myAudio.volume = 0.5;
          

          如果音頻文件設(shè)置了muted為true,則myAudio.volume的返回值是0。

          playbackRate

          playbackRate是一個(gè)可讀兼可寫(xiě)的屬性,用來(lái)設(shè)置或獲取當(dāng)前媒體文件的播放速率,值為數(shù)值,例如:

          // 獲取音頻播放速率
          var audioSpeed = audio.playbackRate;
          // 設(shè)置音頻設(shè)置播放速率為正常速度的1.5倍
          audio.playbackRate = 1.5;
          

          速率范圍

          根據(jù)文檔顯示,Gecko內(nèi)核瀏覽器速率范圍是0.25到5.0,超出這個(gè)范圍就靜音。

          對(duì)于Chrome瀏覽器,我自己實(shí)地測(cè)試了下,速率上限居然可以到16,如下圖:


          然后,此屬性兼容性不錯(cuò),IE9+都支持。

          paused

          paused是一個(gè)只讀屬性,表示當(dāng)前音頻是否處于暫停狀態(tài)。

          // true或false
          console.log(myAudio.paused);
          

          未播放或者播放暫停都會(huì)返回true。

          四、播放與暫停等JS方法

          play()

          音頻播放示意,沒(méi)有額外參數(shù):

          myAudio.play();
          

          需要注意的是,目前在現(xiàn)代瀏覽器下,無(wú)論是桌面端還是移動(dòng)端,執(zhí)行myAudio.play()不總是有效果的。

          目前策略是,web網(wǎng)頁(yè)需要至少又一次可信任的用戶(hù)行為后,才能myAudio.play()播放才可以執(zhí)行,否則會(huì)報(bào)錯(cuò)。


          可信任的用戶(hù)行為包括touchstart觸摸或者click點(diǎn)擊。

          pause()

          音頻暫停示意,沒(méi)有額外參數(shù):

          myAudio.pause();
          

          音頻元素是沒(méi)有stop()方法的,如果你想要實(shí)現(xiàn)音頻的stop()效果,可以先設(shè)置currentTime屬性值為0,然后在執(zhí)行pause()方法。

          canPlayType()

          canPlayType()可以用來(lái)檢測(cè)瀏覽器是否支持某種類(lèi)型的音頻文件,支持一個(gè)mime type值作為參數(shù)。使用示意:

          if (myAudio.canPlayType('audio/mpeg')) {
           // 如果支持mp3
           // 這里搞事情
          }
          

          canPlayType()方法可以返回下面三個(gè)值中的某一個(gè):

          1. probably
          2. maybe
          3. ""(空字符串)

          實(shí)際開(kāi)發(fā)的時(shí)候,只要不是空字符串,我們都可以認(rèn)為是支持的,因此,直接使用if弱匹配返回值即可,例如:

          var myAudio = document.createElement('audio');
          if (myAudio.canPlayType('audio/mpeg')) {
           myAudio.setAttribute('src','audiofile.mp3');
          }
          if (myAudio.canPlayType('audio/ogg')) {
           myAudio.setAttribute('src','audiofile.ogg');
          }
          

          load()

          觸發(fā)音頻文件的加載。如果瀏覽器不支持preload屬性,則此方法也不會(huì)有效果。

          此方法沒(méi)有額外參數(shù):

          myAudio.load();
          

          五、音頻媒體加載事件

          下面講講關(guān)于音頻加載及相關(guān)處理,根據(jù)我實(shí)際項(xiàng)目中的實(shí)踐,這類(lèi)加載事件在移動(dòng)端,尤其iOS Safari并不總能觸發(fā),因?yàn)閜reload以及autoplay等屬性的限制。

          loadstart

          loadstart事件簡(jiǎn)單地告訴我們加載過(guò)程已經(jīng)開(kāi)始,瀏覽器正在連接到媒體。

          myAudio.addEventListener("loadstart", function() {
           // 抓取文件
          });
          

          durationchange

          如果你想盡快知道音頻文件的播放時(shí)長(zhǎng),則durationchange事件非常管用,因?yàn)橐纛l文件默認(rèn)duration初始值是NaN,當(dāng)準(zhǔn)確時(shí)長(zhǎng)返回時(shí)候,會(huì)觸發(fā)durationchange,此時(shí)我們就可以快速顯示音頻播放時(shí)間了。

          通常實(shí)際開(kāi)發(fā),我們會(huì)使用00:00占位,durationchange事件觸發(fā)后在替換為準(zhǔn)確的總播放時(shí)間。

          myAudio.addEventListener("durationchange", function() {
           // 可以顯示播放時(shí)長(zhǎng)了喲
          });
          

          loadedmetadata

          當(dāng)?shù)谝粋€(gè)音頻文件字節(jié)數(shù)據(jù)到達(dá)時(shí),會(huì)觸發(fā)loadeddata事件。雖然播放頭已經(jīng)就位,但還沒(méi)有準(zhǔn)備好播放。

          myAudio.addEventListener("loadeddata", function() {
           // 可以顯示播放頭
          });
          

          progress

          progress事件在媒體文件仍然在下載中的時(shí)候觸發(fā),通常各種loading效果的顯示就是在這個(gè)事件中。

          myAudio.addEventListener("progress", function() {
           // 你可以讓用戶(hù)知道媒體文件正在下載
          });
          

          canplay

          當(dāng)媒體文件可以播放的時(shí)候會(huì)觸發(fā)canplay事件。

          我們?cè)谧远x音頻播放器的時(shí)候,可以默認(rèn)把一些按鈕disabled禁用,等可以播放的時(shí)候再恢復(fù)為enabled,此時(shí)就可以使用canplay事件。

          myAudio.addEventListener("canplay", function() {
           // 音頻可以播放了
          });
          

          canplaythrough

          canplaythrough事件在音頻文件可以從頭播放到尾時(shí)候觸發(fā)。這種情況包括音頻文件已經(jīng)從頭到尾加載完畢了,或者瀏覽器認(rèn)為一定可以按時(shí)下載,不會(huì)發(fā)生緩沖停止。

          myAudio.addEventListener("canplaythrough", function() {
           // 音頻可以不發(fā)生緩沖從頭播放到結(jié)束
          });
          

          音頻事件觸發(fā)的順序

          媒體事件加載順序如下:

          loadstart → durationchange → loadedmetadata → loadeddata → progress → canplay → canplaythrough

          加載中斷事件

          還有一些事件實(shí)在媒體加載過(guò)程出現(xiàn)某種中斷時(shí)將觸發(fā)。

          suspend

          即使文件尚未完全下載,也不再拉取媒體數(shù)據(jù)。

          abort

          不是因?yàn)槌鲥e(cuò)而導(dǎo)致的媒體數(shù)據(jù)下載中止。

          error

          媒體下載過(guò)程中錯(cuò)誤。例如突然無(wú)網(wǎng)絡(luò)了。或者文件地址不對(duì)。

          emptied

          媒體緩沖區(qū)已被清空,可能是由于錯(cuò)誤或調(diào)用了load()方法重新加載。

          stalled

          媒體數(shù)據(jù)意外地不再可用。

          六、音頻媒體播放事件

          下面介紹一些與媒體文件播放狀態(tài)相關(guān)的一些事件。

          timeupdate

          每次currentTime屬性值發(fā)生變化的時(shí)候會(huì)觸發(fā)timeupdate事件。

          實(shí)際開(kāi)發(fā)的時(shí)候,這個(gè)事件每250毫秒出發(fā)一次。這個(gè)事件可用來(lái)實(shí)時(shí)顯示播放進(jìn)度。

          myAudio.addEventListener("timeupdate", function() {
           // 更新與播放進(jìn)度相關(guān)的內(nèi)容
          });
          

          playing

          音頻文件在缺少媒體信息(如時(shí)長(zhǎng)等)的時(shí)候,播放會(huì)被迫停止,如果之后在啟動(dòng)播放,會(huì)觸發(fā)playing事件。

          waiting

          音頻文件因?yàn)槿鄙倜襟w信息(如時(shí)長(zhǎng)等)導(dǎo)致播放停止時(shí)會(huì)觸發(fā)waiting事件。

          play

          play事件在play()方法生效,或者autoplay導(dǎo)致播放開(kāi)始時(shí)候觸發(fā),此事件觸發(fā)的播放狀態(tài)一定是一個(gè)從暫停到播放。

          pause

          pause事件在pause()方法執(zhí)行并生效后觸發(fā),此事件觸發(fā)需要一個(gè)從播放到暫停的狀態(tài)變化。

          ended

          當(dāng)整個(gè)音頻文件播放完畢的時(shí)候觸發(fā)ended事件。

          myAudio.addEventListener("ended", function() {
           // 當(dāng)音軌播放完畢時(shí)候做你想做的事情
          });
          

          volumechange

          音量發(fā)生變化的時(shí)候會(huì)觸發(fā)volumechange事件,包括靜音行為。

          ratechange

          播放速率發(fā)生變化的時(shí)候會(huì)觸發(fā)ratechange事件。

          七、緩沖相關(guān)的屬性和方法

          媒體文件的播放進(jìn)度我們可以使用currentTime和duration屬性獲取,但是有時(shí)候,我們希望知道緩沖加載的進(jìn)度,此時(shí)可以使用下面幾個(gè)和緩沖相關(guān)屬性和方法。

          buffered

          此屬性讓我們知道音頻的哪些部分已被緩沖(提前下載)。它返回一個(gè)稱(chēng)為T(mén)imeRanges的對(duì)象。

          myBufferedTimeRanges = myAudio.buffered;
          

          seekable

          seekable屬性通知您是否可以直接跳到媒體的該部分,而不需要進(jìn)一步緩沖。

          mySeekableTimeRanges = myAudio.seekable;
          

          Buffering相關(guān)事件

          seeking

          當(dāng)媒體資源正在請(qǐng)求是會(huì)觸發(fā)seeking事件。

          seeked

          當(dāng)seeking屬性變成false時(shí)候會(huì)觸發(fā)seeked事件。

          有關(guān)緩沖以及TimeRanges更深入具體的知識(shí),可以參見(jiàn)這篇MDN文檔。

          八、結(jié)語(yǔ)與參考文檔

          本文展示的這些<audio>音頻元素相關(guān)的屬性和方法以及各種回調(diào)事件,對(duì)于<video>視頻元素同樣受用,基本上都是一模一樣的,很多自動(dòng)播放以及媒體自動(dòng)加載策略也是一致的。

          本文展示的這些API并不是全部,如果發(fā)現(xiàn)有遺漏,歡迎大家補(bǔ)充。

          載說(shuō)明:原創(chuàng)不易,未經(jīng)授權(quán),謝絕任何形式的轉(zhuǎn)載

          Midjourney 創(chuàng)作,未來(lái)API

          大家好,隨著技術(shù)的迅速發(fā)展,開(kāi)發(fā)者們擁有了越來(lái)越多的令人驚嘆的新工具和API。但是,我們發(fā)現(xiàn)在100多個(gè)API中,只有5%的API被開(kāi)發(fā)者們積極地使用。

          下面讓我們來(lái)看看一些有用的Web API,它們可以幫助你將你的網(wǎng)站推向未來(lái)的巔峰!

          1、屏幕捕獲API

          屏幕捕獲API,正如其名,允許你捕獲屏幕內(nèi)容,讓制作屏幕錄像變得輕而易舉。你需要一個(gè)視頻元素來(lái)顯示捕獲的屏幕。點(diǎn)擊開(kāi)始按鈕即可開(kāi)始屏幕捕獲。

          <video id="preview" autoplay>
            Your browser doesn't support HTML5.
          </video>
          <button id="start" class="btn">Start</button>
          // 獲取HTML元素
          const previewElem = document.getElementById("preview"); // 預(yù)覽元素
          const startBtn = document.getElementById("start"); // 開(kāi)始按鈕元素
          
          // 異步函數(shù),開(kāi)始錄制屏幕和聲音
          async function startRecording() {
            previewElem.srcObject = // 將預(yù)覽元素的srcObject屬性設(shè)置為獲取到的屏幕和聲音媒體流
              await navigator.mediaDevices.getDisplayMedia({
                video: true, // 錄制視頻
                audio: true, // 錄制聲音
              });
          }
          
          // 為開(kāi)始按鈕添加點(diǎn)擊事件監(jiān)聽(tīng)器,點(diǎn)擊時(shí)調(diào)用startRecording函數(shù)
          startBtn.addEventListener("click", startRecording);

          2、Web Share API

          Web Share API 允許你從一個(gè)網(wǎng)頁(yè)分享文本、鏈接甚至是文件到設(shè)備上安裝的其他應(yīng)用程序。

          // 異步函數(shù),處理分享事件
          async function shareHandler() {
            // 調(diào)用navigator.share方法進(jìn)行分享,傳入分享內(nèi)容的相關(guān)信息
            navigator.share({
              title: "Tapajyoti Bose | Portfolio", // 分享標(biāo)題
              text: "Check out my website", // 分享文本
              url: "https://tapajyoti-bose.vercel.app/", // 分享鏈接
            });
          }
          
          // 給某個(gè)元素添加點(diǎn)擊事件監(jiān)聽(tīng)器,點(diǎn)擊時(shí)調(diào)用shareHandler函數(shù)
          someElement.addEventListener("click", shareHandler);

          注意:要使用 Web Share API,你需要從用戶(hù)那里獲得互動(dòng),例如按鈕點(diǎn)擊或觸摸事件。

          3、Intersection Observer API

          Intersection Observer API 允許你檢測(cè)元素何時(shí)進(jìn)入或離開(kāi)視口。這對(duì)于實(shí)現(xiàn)無(wú)限滾動(dòng)非常有用。

          簡(jiǎn)單的例子

          // 創(chuàng)建一個(gè)IntersectionObserver實(shí)例,觀察特定元素
          const observer = new IntersectionObserver((entries) => {
            // 遍歷每個(gè)entry,判斷是否在視口內(nèi)
            entries.forEach((entry) => {
              if (entry.isIntersecting) {
                // 元素進(jìn)入視口,執(zhí)行相應(yīng)操作
              } else {
                // 元素離開(kāi)視口,執(zhí)行相應(yīng)操作
              }
            });
          });
          
          // 將需要觀察的元素傳遞給IntersectionObserver實(shí)例
          const target = document.querySelector(".target");
          observer.observe(target);

          一個(gè)復(fù)雜的分頁(yè)滾動(dòng)(React版本)

          <div id="root"></div>
          /* The entire styling is totally optional */
          
          * {
            font-family: Roboto;
          }
          
          body {
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            text-align: center;
          }
          
          .item {
            width: 80vw;
            margin: 12px 0;
            padding: 32px;
            border-radius: 8px;
            font-size: larger;
          }
          
          .loader {
            border: 8px solid #cccccc;
            border-top: 8px solid #3498db;
            border-radius: 50%;
            width: 40px;
            height: 40px;
            animation: spin 0.6s linear infinite;
            display: inline-block;
            margin: 8px auto;
          }
          
          @keyframes spin {
            0% {
              transform: rotate(0deg);
            }
            100% {
              transform: rotate(360deg);
            }
          }
          
          // 聲明常量MAX_PAGES,表示可加載的最大頁(yè)數(shù)
          const MAX_PAGES = 5;
          
          // 生成隨機(jī)顏色的函數(shù)
          const generateRandomColor = () => {
            const characters = "0123456789ABCDEF";
            let color = "#";
            for (let i = 0; i < 6; i++) {
              color += characters[Math.floor(Math.random() * 16)];
            }
            return color;
          };
          
          // 定義Item組件,接受children、color和reference屬性,返回帶有顏色的div元素
          const Item = ({ children, color, reference }) => {
            return (
              <div className="item" style={{ backgroundColor: color }} ref={reference}>
                {children}
              </div>
            );
          };
          
          // 定義App組件
          const App = () => {
            // 定義狀態(tài)變量:items-加載的數(shù)據(jù)數(shù)組、isLoading-是否正在加載數(shù)據(jù)、hasMore-是否還有更多數(shù)據(jù)可加載、pages-已加載的頁(yè)數(shù)
            const [items, setItems] = React.useState([]);
            const [isLoading, setIsLoading] = React.useState(false);
            const [hasMore, setHasMore] = React.useState(true);
            const [pages, setPages] = React.useState(0);
          
            // 定義ref引用observer
            const observer = React.useRef();
          
            // 在掛載時(shí)更新items數(shù)組和pages變量
            React.useEffect(() => {
              updateItems();
              setPages((pages) => pages + 1);
            }, []);
          
            // 定義lastItemRef回調(diào)函數(shù),用于觀察最后一個(gè)元素是否進(jìn)入視口
            const lastItemRef = React.useCallback(
              (node) => {
                if (isLoading) return;
                if (observer.current) observer.current.disconnect();
          
                observer.current = new IntersectionObserver((entries) => {
                  if (entries[0].isIntersecting && hasMore) {
                    if (pages < MAX_PAGES) {
                      updateItems();
                      setPages((pages) => pages + 1);
                    } else {
                      setHasMore(false);
                    }
                  }
                });
          
                if (node) observer.current.observe(node);
              },
              [isLoading, hasMore]
            );
          
            // 定義updateItems異步函數(shù),更新items數(shù)組和isLoading狀態(tài)變量
            const updateItems = async () => {
              setIsLoading(true);
              await new Promise((resolve) => setTimeout(resolve, 1000));
          
              setItems((currItems) => {
                const lastItem = currItems.length;
                const updatedItems = [...currItems];
                for (let i = 1; i <= 5; i++) {
                  const item = {
                    count: lastItem + i,
                    color: generateRandomColor()
                  };
                  updatedItems.push(item);
                }
                return updatedItems;
              });
          
              setIsLoading(false);
            };
          
            // 返回頁(yè)面結(jié)構(gòu)
            return (
              <React.Fragment>
                <h1>Infinite Scroll Demo</h1>
                {items.map((item, index) =>
                  index + 1 === items.length ? (
                    <Item reference={lastItemRef} key={index} color={item.color}>
                      {item.count}
                    </Item>
                  ) : (
                    <Item key={index} color={item.color}>
                      {item.count}
                    </Item>
                  )
                )}
                {isLoading && <div className="loader" />}
              </React.Fragment>
            );
          };
          
          // 將App組件渲
          

          注意:此示例使用React,因?yàn)檫@是我個(gè)人偏好,但你可以使用任何框架或原生JavaScript。

          4、Clipboard API

          Clipboard API 允許你讀取和寫(xiě)入剪貼板中的數(shù)據(jù)。這對(duì)于實(shí)現(xiàn)復(fù)制到剪貼板的功能非常有用。

          // 定義異步函數(shù)copyHandler,將指定文本寫(xiě)入剪貼板
          async function copyHandler() {
            const text = "https://tapajyoti-bose.vercel.app/";
            navigator.clipboard.writeText(text);
          }
          

          5、Screen Wake Lock API

          你是否曾經(jīng)想過(guò)在觀看視頻時(shí)如何防止屏幕關(guān)閉?這就是因?yàn)槭褂昧?Screen Wake Lock API。

          // 聲明變量wakeLock
          let wakeLock = null;
          
          // 定義異步函數(shù)lockHandler,請(qǐng)求屏幕喚醒鎖定
          async function lockHandler() {
            wakeLock = await navigator.wakeLock.request("screen");
          }
          
          // 定義異步函數(shù)releaseHandler,釋放屏幕喚醒鎖定
          async function releaseHandler() {
            await wakeLock.release();
            wakeLock = null;
          }
          
          // 注意:只有頁(yè)面已經(jīng)在屏幕上可見(jiàn)時(shí),才能使用Screen Wake Lock API。否則會(huì)拋出錯(cuò)誤。

          6、Screen Orientation API

          Screen Orientation API 允許你檢查屏幕的當(dāng)前方向,甚至鎖定到特定的方向。

          // 定義異步函數(shù)lockHandler,鎖定屏幕方向?yàn)樨Q屏
          async function lockHandler() {
            await screen.orientation.lock("portrait");
          }
          
          // 定義函數(shù)releaseHandler,解除屏幕方向鎖定
          function releaseHandler() {
            screen.orientation.unlock();
          }
          
          // 定義函數(shù)getOrientation,返回屏幕當(dāng)前的方向
          function getOrientation() {
            return screen.orientation.type;
          }
          

          7、Fullscreen API

          Fullscreen API 允許你將一個(gè)元素或整個(gè)頁(yè)面顯示為全屏。

          // 定義異步函數(shù)enterFullscreen,將整個(gè)文檔元素進(jìn)入全屏模式
          async function enterFullscreen() {
            await document.documentElement.requestFullscreen();
          }
          
          // 定義異步函數(shù)exitFullscreen,退出全屏模式
          async function exitFullscreen() {
            await document.exitFullscreen();
          }
          
          // 注意:為了使用 Fullscreen API,同樣需要用戶(hù)的交互。

          注意:同樣需要用戶(hù)的交互才能使用 Fullscreen API。

          兼容性

          這些API,目前在主流瀏覽器中都得到了很好的支持,包括Google Chrome、Mozilla Firefox、Safari和Microsoft Edge等瀏覽器。但是,在舊版瀏覽器中可能會(huì)存在一些兼容性問(wèn)題。因此,在開(kāi)發(fā)使用時(shí),應(yīng)該考慮到不同瀏覽器的兼容性問(wèn)題,并根據(jù)實(shí)際情況選擇是否使用這些API。

          結(jié)束

          非常棒!通過(guò)本文的介紹和代碼示例,相信大家已經(jīng)了解了這些有用的Web API,并且知道如何使用它們來(lái)提升網(wǎng)站的用戶(hù)體驗(yàn)和功能。雖然這些API在不同瀏覽器中的兼容性可能存在一些問(wèn)題,但我們可以通過(guò)適當(dāng)?shù)募嫒菪詸z查和回退方案來(lái)確保網(wǎng)站的穩(wěn)定性和可靠性。總之,Web API為開(kāi)發(fā)者提供了強(qiáng)大的工具和資源,讓我們一起探索并不斷嘗試新的技術(shù)和功能,為用戶(hù)帶來(lái)更好的體驗(yàn)和價(jià)值。

          今天的分享就到這里,感謝你的閱讀,希望能夠幫助到你,文章創(chuàng)作不易,如果你喜歡我的分享,別忘了點(diǎn)贊轉(zhuǎn)發(fā),讓更多有需要的人看到,最后別忘記關(guān)注「前端達(dá)人」,你的支持將是我分享最大的動(dòng)力,后續(xù)我會(huì)持續(xù)輸出更多內(nèi)容,敬請(qǐng)期待。

          原文:https://tapajyoti-bose.medium.com/7-javascript-web-apis-to-build-futuristic-websites-you-didnt-know-12b737ccf594

          作者:Tapajyoti Bose

          非直接翻譯,有自行改編和添加部分,翻譯水平有限,難免有疏漏,歡迎指正


          主站蜘蛛池模板: 亚洲乱码一区二区三区国产精品 | 国产未成女一区二区三区| 亚洲AV综合色区无码一区爱AV| 2018高清国产一区二区三区| 国模丽丽啪啪一区二区| 国产精品亚洲一区二区三区久久 | 无码精品人妻一区二区三区影院| 无码人妻视频一区二区三区| 精品国产一区二区22| 国模精品一区二区三区视频| 91精品乱码一区二区三区| 久久91精品国产一区二区| 国产一区二区三区精品视频| 亚洲一区二区三区在线播放| 精品一区二区三区在线视频观看| 亚洲丶国产丶欧美一区二区三区 | 一区二区三区无码高清| 国产视频一区二区| 日本在线视频一区二区三区 | 日韩成人一区ftp在线播放| AV无码精品一区二区三区| 无码aⅴ精品一区二区三区浪潮| 91久久精一区二区三区大全| 夜夜添无码试看一区二区三区| 国产日韩高清一区二区三区 | 日韩精品久久一区二区三区| 在线播放偷拍一区精品| 亚洲Av永久无码精品一区二区| 中文字幕视频一区| 呦系列视频一区二区三区| 丝袜美腿一区二区三区| 手机福利视频一区二区| 国产精品视频一区国模私拍 | 亚洲国产高清在线一区二区三区| 日本一区二区三区中文字幕| 久久精品中文字幕一区| 国产一区二区精品尤物| 一区二区视频在线观看| 精品少妇人妻AV一区二区三区| 亚洲爆乳精品无码一区二区| 福利在线一区二区|