整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          如何使用 JavaScript 錄制屏幕?

          色字體,選擇“標星公眾號

          優質文章,第一時間送達

          屏幕錄制?截屏?網頁生成圖片?幀圖?說到錄屏,我一開始想到的是前面這些詞。大致的想法是持續的生成當前頁面的截圖,然后把這些幀圖再合并成一個視頻文件。前端頁面生成圖片我們應該比較熟悉的是html2canvas。另外也有一些現成的庫可以使用來進行屏幕的錄制,RecordRTC上就有很多屏幕錄制的實現。有聲音(Audio)、視頻(Video)、屏幕(Screen)的錄制;有針對canvas的錄制等等,一共有三十多個示例。這里主要想簡單的講一講原生的 Screen Capture API。參見:Using the Screen Capture API

          一、屏幕內容的捕獲

          navigator.mediaDevices.getDisplayMedia

          該方法會返回一個promise, 該promise會resolve當前屏幕內容的實時數據流。

          使用 async / await 實現如下:

          async function startCapture(displayMediaOptions) { let captureStream = ;
          try { captureStream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions); } catch(err) { console.error("Error: " + err); } return captureStream;}

          使用 promise 的方式實現如下:

          function startCapture(displayMediaOptions) { let captureStream = ;
          return navigator.mediaDevices.getDisplayMedia(displayMediaOptions) .catch(err => { console.error("Error:" + err); return ; });}

          我們在獲取屏幕數據的時候有可能會獲取到一些敏感信息,所有在使用getDisplayMedia的時候,為了安全考慮,會彈出一個選擇框,然用戶自己選擇需要共享那一部分的內容。可以共享當前屏幕,也可以共享其他的應用窗口和瀏覽器的其他標簽頁。

          二、參數配置:

          我們在上面的實現中可以看到, 傳遞給startCapture函數的參數為displayMediaOptions。這個參數是用于配置返回數據流的。數據形式如下:

          const displayMediaOptions = { video: { cursor: "never" },  audio: false,  logicalSurface: false, };

          開可以針對音視頻做詳細的配置:

          const gdmOptions = { video: { cursor: "always" // 始終顯示鼠標信息 }, // audio 配置信息是可選的 audio: { echoCancellation: true,  noiseSuppression: true, sampleRate: 44100 } }

          三、示例

          HTML:

          <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Screen Record</title> <link rel="stylesheet" href="./css/index.css"></head><body> <p>This example shows you the contents of the selected part of your display. Click the Start Capture button to begin.</p> <p><button id="start">Start Capture</button>&nbsp;<button id="stop">Stop Capture</button></p> <video id="video" autoplay></video> <br> <strong>Log:</strong> <br> <pre id="log"></pre> <script src="./js/index.js"></script></body></html>

          CSS:

          #video { border: 1px solid #999; width: 98%; max-width: 860px; } .error { color: red; } .warn { color: orange; } .info { color: darkgreen; }

          JS:

          const videoElem = document.getElementById("video");const logElem = document.getElementById("log");const startElem = document.getElementById("start");const stopElem = document.getElementById("stop");
          const displayMediaOptions = { video: { cursor: "never" }, audio: false};
          startElem.addEventListener("click", function(evt) { startCapture;}, false);stopElem.addEventListener("click", function(evt) { stopCapture;}, false);console.log = msg => logElem.innerHTML += `${msg}<br>`;console.error = msg => logElem.innerHTML += `<span class="error">${msg}</span><br>`;console.warn = msg => logElem.innerHTML += `<span class="warn">${msg}<span><br>`;console.info = msg => logElem.innerHTML += `<span class="info">${msg}</span><br>`;
          async function startCapture { logElem.innerHTML = "";
          try { videoElem.srcObject = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions); dumpOptionsInfo; } catch(err) { console.error("Error: " + err); }}
          function stopCapture(evt) { let tracks = videoElem.srcObject.getTracks;
          tracks.forEach(track => track.stop); videoElem.srcObject = ;}
          function dumpOptionsInfo { const videoTrack = videoElem.srcObject.getVideoTracks[0]; console.info("Track settings:"); console.info(JSON.stringify(videoTrack.getSettings, , 2)); console.info("Track constraints:"); console.info(JSON.stringify(videoTrack.getConstraints, , 2));}

          效果如下:

          點擊Start Capture 之后選擇需要共享的部分就可以共享如下的內容:

          點擊Stop Capture即可˙停止錄制共享。

          這個例子只是調取接口獲取到當前分享屏幕的數據流,并通過video的形式顯示出來。我們在拿到數據流信息這個,可以把這些信息上傳到服務器,生成相應的視頻文件。也可以結合websocket之類的處理方式,實現實時的屏幕共享功能。

          作者:飯等米

          鏈接:segmentfault.com/a/1190000020267689

          如果喜歡本篇文章,歡迎。關注訂閱號「Web項目聚集地」,回復「進群」即可進入無廣告技術交流。

          1.2. 4. 5.6.

          件傳遞有兩種方式,冒泡和捕獲。事件傳遞定義了元素事件觸發的順序,在冒泡中,內部元素的事件會先被觸發,然后在觸發外部元素,如先觸發p元素然后觸發div元素。在捕獲事件中,外部元素先被觸發,然后內部事件觸發。addEventListener() 方法可以指定 "useCapture" 參數來設置傳遞類型:addEventListener(event, function, useCapture);

          創建新的HTML元素(節點)appendChild()

          HTML Collection與NodeList的區別:NodeList 與 HTMLCollection 有很多類似的地方。NodeList 與 HTMLCollection 都與數組對象有點類似,可以使用索引 (0, 1, 2, 3, 4, ...) 來獲取元素。NodeList 與 HTMLCollection 都有 length 屬性。節點列表不是一個數組!節點列表無法使用數組的方法: valueOf(), pop(), push(), 或 join() 。

          件流:

          事件冒泡

          取消冒泡:oEvent.cancelBubble=true

          <html>
          <head>
          <meta charset="utf-8">
          <title>無標題文檔</title>
          <style>
          #div1 {width:400px; height:300px; background:#CCC; display:none;}
          </style>
          <script>
          window.onload=function ()
          {
              var oBtn=document.getElementById('btn1');
              var oDiv=document.getElementById('div1');
          
              oBtn.onclick=function (ev)
              {
              var oEvent=ev||event;
          
              oDiv.style.display='block';
              //alert('按鈕被點擊了');
          
              oEvent.cancelBubble=true; //取消事件冒泡,是解決許多問題的方法和手段
              };
          
              document.onclick=function ()
              {
              oDiv.style.display='none';
              //alert('document被點擊了');
              };
          };
          </script>
          </head>
          <body>
          <input id="btn1" type="button" value="顯示" />
          <div id="div1">
          </div>
          </body>
          </html>

          冒泡型事件:

          <html>
          <head>
          <title>冒泡型事件</title>
          <script language="javascript">
          function add(sText){
          var oDiv = document.getElementById("display");
          oDiv.innerHTML += sText; //輸出點擊順序
          }
          </script>
          </head>
          <body onclick="add('body<br>');">
          <div onclick="add('div<br>');">
          <p onclick="add('p<br>');">Click Me</p>
          </div>
          <div id="display"></div>
          </body>
          </html>

          執行順序:p對象 -> div對象 -> body對象

          冒泡型事件執行順序::由內到外(p -> div -> body -> document)

          注意: DOM 0級只有冒泡, 沒有捕獲

          捕獲型事件

          相對于IE使用冒泡型事件, Netscape使用了另一種稱為捕獲型事件(eventcapturing)的解決方案;

          addEventListener(事件名稱,函數, bCapture)

          removeEventListener(事件名稱, 函數, bCapture)

          事件監聽函數第三個參數bCapture確定是冒泡型還是捕獲型事件(true:捕獲 false:冒泡,默認值false)

          <!DOCTYPE html>
          <html>
          <head>
          <style>
          div {
          background-color: coral;
          border: 1px solid;
          padding: 50px;
          }
          </style>
          </head>
          <body>
          <div id="myDiv2">
          <p id="myP2">點擊該段落, 我是捕獲</p>
          </div>
          <script>
          document.getElementById("myP2").addEventListener("click", function() {
          alert("你點擊了 P 元素!");
          }, true);
          document.getElementById("myDiv2").addEventListener("click", function() {
          alert("你點擊了 DIV 元素!");
          }, true);
          </script>
          </body>
          </html>

          執行順序: div對象 -> p對象

          捕獲型事件執行順序:由外到內(如:document -> body -> div -> p)

          冒泡型:事件從內部往外部依次執行。

          捕捉型:事件從外部往內部依次執行。

          事件監聽

          通用監聽方法:

          1.直接在HTML標簽中分配事件處理函數:

          <script language="javascript">
          function add(sText){
          var oDiv = document.getElementById("display");
          oDiv.innerHTML += sText; //輸出點擊順序
          }
          </script>
          </head>
          <body onclick="add('body<br>');">
          <div onclick="add('div<br>');">
          <p onclick="add('p<br>');">Click Me</p>
          </div>
          <div id="display"></div>
          </body>

          2.結構與行為的分離:

          <html>
          <head>
          <title>監聽函數</title>
          <script language="javascript">
          window.onload = function(){
          var oP = document.getElementById("myP"); //找到對象
          oP.onclick = function(){ //設置事件監聽函數
          alert('我被點擊了');
          }
          }
          </script>
          </head>
          <body>
          <div>
          <p id="myP">Click Me</p>
          </div>
          </body>
          </html>

          事件監聽的作用:

          <!DOCTYPE HTML>
          <html>
          <head>
          <meta charset="utf-8">
          <title>無標題文檔</title>
          <script>
          window.onload=function ()
          {
          alert('a');
          };
          window.onload=function ()
          {
          alert('b');
          };
          </script>
          </head>
          <body>
          </body>
          </html>

          以上程序只彈出alert('b');

          理解:對同一對象執行兩次事件(同一事件類型)處理函數時,往往只能只執行后一個

          因此如果要讓腳本在本瀏覽器中正常運行的話,就必須使用瀏覽器所支持的事件監聽器

          IE中的監聽方法:

          attachEvent(事件名稱, 函數), 綁定事件處理函數 attach: 貼上, 附著

          detachEvent(事件名稱, 函數), 解除綁定 detach: 分離, 拆開

          注意:IE只支持冒泡型事件監聽, 沒有第三個參數, 事件名稱前要加"on";

          <html>
          <head>
          <title>多個監聽函數</title>
          <script language="javascript">
          function fnClick1(){
          alert("我被fnClick1點擊了");
          }
          function fnClick2(){
          alert("我被fnClick2點擊了");
          //oP.detachEvent("onclick",fnClick1); //刪除監聽函數1
          }
          var oP;
          window.onload = function(){
          oP = document.getElementById("myP"); //找到對象
          oP.attachEvent("onclick",fnClick1); //添加監聽函數1
          oP.attachEvent("onclick",fnClick2); //添加監聽函數2
          }
          </script>
          </head>
          <body>
          <div>
          <p id="myP">Click Me</p>
          </div>
          </body>
          </html>

          標準DOM的事件監聽:

          addEventListener(事件名稱,函數, 捕獲)

          element.addEventListener(event, function, useCapture)

          removeEventListener(事件名稱, 函數, 捕獲)

          element.removeEventListener(event, function, useCapture)

          bCapture 是用于冒泡階段還是捕獲階段(true:捕獲 false:冒泡,默認值false)

          注意:IE9版本已支持

          <html>
          <head>
          <title>標準DOM的事件監聽</title>
          <script language="javascript">
          function fnClick1(){
          alert("我被fnClick1點擊了");
          //oP.removeEventListener("click",fnClick2,false); //刪除監聽函數2
          }
          function fnClick2(){
          alert("我被fnClick2點擊了");
          }
          var oP;
          window.onload = function(){
          oP = document.getElementById("myP"); //找到對象
          oP.addEventListener("click",fnClick1,false); //添加監聽函數1
          oP.addEventListener("click",fnClick2,false); //添加監聽函數2
          }
          </script>
          </head>
          <body>
          <div>
          <p id="myP">Click Me</p>
          </div>
          </body>
          </html>

          編寫兼容性事件監聽函數

          function addEvent(obj, ev, fn){
              if(obj.addEventListener){
              obj.addEventListener(ev, fn, false);
              }else{
              obj.attachEvent('on'+ev, fn);
              }
          }
          function removeEvent(obj, ev, fn){
              if(obj.removeEventListener){
              obj.addEventListener(ev, fn, false);
              }else{
              obj.attachEvent('on'+ev, fn);
              }
          }

          實例:


          主站蜘蛛池模板: 精品日韩一区二区| 精品人妻AV一区二区三区| 亚洲国产精品自在线一区二区| 亚洲综合无码一区二区| 色噜噜狠狠一区二区三区果冻| 国模无码一区二区三区| 日韩视频免费一区二区三区| 北岛玲在线一区二区| 日韩精品一区二区三区在线观看| 肉色超薄丝袜脚交一区二区| 亚洲一区二区三区在线网站| 在线免费视频一区| 伊人久久精品无码av一区| 久久精品无码一区二区三区不卡| 四虎永久在线精品免费一区二区| 亚洲AV福利天堂一区二区三 | 日韩一区二区三区不卡视频 | 国产精品伦子一区二区三区| 日本在线视频一区二区三区| A国产一区二区免费入口| 亚洲午夜精品一区二区| 天天爽夜夜爽人人爽一区二区| 国产精品久久亚洲一区二区| 国产一区二区三区乱码在线观看| 亚洲熟妇av一区二区三区| 亚洲AV乱码一区二区三区林ゆな| 日本无码一区二区三区白峰美| 国产福利一区二区三区在线观看 | 日韩人妻精品一区二区三区视频| 日本一区二区三区四区视频| 国产精品亚洲一区二区三区在线观看| 中文字幕一区日韩在线视频 | 一区二区在线视频观看| 亚洲熟妇av一区二区三区| 国产一区二区三区不卡AV| 久久青草精品一区二区三区| 日韩国产免费一区二区三区| 视频在线一区二区| 一区二区三区在线免费| 亚洲av无码一区二区三区四区| 成人国内精品久久久久一区|