欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

用JavaScript實現(xiàn)瀏覽器截圖功能的全過程

 更新時間:2025年07月22日 10:33:56   作者:ZCKKKing  
在Web開發(fā)中實現(xiàn)網(wǎng)頁截圖功能可以幫助我們保存網(wǎng)頁內(nèi)容、生成海報、制作截圖分享等,這篇文章主要介紹了用JavaScript實現(xiàn)瀏覽器截圖功能的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

最近項目中要實現(xiàn)一個需求:
 

用戶希望在上傳文件時能夠直接截圖上傳,并且要求能夠截圖瀏覽器外的內(nèi)容。

多方查找之下找到了類似的解決方案,但個人感覺操作上有些抽象,僅供參考。

HTML部分

  • 截圖開始的按鈕
    <button id="start-screenshot" class="button">開始截圖</button>
    
  • 這里是canvas部分
    <div id="screenshot-container">
           <canvas id="screenshot-canvas"></canvas>
           <div class="selection-area" id="selection-area" style="display: none;"></div>
           <div class="toolbar" id="screenshot-toolbar" style="display: none;">
               <button id="confirm-screenshot">確認(rèn)</button>
               <button id="cancel-screenshot">取消</button>
           </div>
    </div>
    

CSS部分

  • 根據(jù)需求自行調(diào)整就好
     #screenshot-container {
         display: none;
         position: fixed;
         top: 0;
         left: 0;
         width: 100%;
         height: 100%;
         z-index: 9999;
     }
    
     #screenshot-canvas {
         position: absolute;
         top: 0;
         left: 0;
         cursor: crosshair;
     }
    
     .selection-area {
         position: absolute;
         border: 2px dashed #12B7F5;
         background-color: rgba(18, 183, 245, 0.1);
         pointer-events: none;
     }
    
     .toolbar {
         position: absolute;
         background-color: white;
         border-radius: 4px;
         box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
         padding: 5px;
         display: flex;
         gap: 5px;
     }
    
     .toolbar button {
         background-color: #12B7F5;
         color: white;
         border: none;
         padding: 5px 10px;
         border-radius: 4px;
         cursor: pointer;
         font-size: 14px;
     }
    
     .toolbar button:hover {
         background-color: #0E9AD7;
     }
    

JS部分(原生JS為例)

  • 獲取dom元素

    const startButton = document.getElementById('start-screenshot'); // 開始截圖按鈕
    const screenshotContainer = document.getElementById('screenshot-container'); // 獲取的圖片展示區(qū)
    const canvas = document.getElementById('screenshot-canvas'); // canvas
    const ctx = canvas.getContext('2d');
    const selectionArea = document.getElementById('selection-area'); // 截圖區(qū)域
    const toolbar = document.getElementById('screenshot-toolbar'); // 截圖時右下角的小彈框
    const confirmButton = document.getElementById('confirm-screenshot'); // 確認(rèn)按鈕
    const cancelButton = document.getElementById('cancel-screenshot'); // 取消按鈕
    
  • 變量定義

    let isCapturing = false;
    let isSelecting = false;
    let startX = 0;
    let startY = 0;
    let endX = 0;
    let endY = 0;
    let screenCapture = null;
    
  • 設(shè)置畫布大小

    function setCanvasSize() {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
    }
    
  • 開始截圖方法

    async function startScreenshot() {
       try {
           // 請求屏幕捕獲
           screenCapture = await navigator.mediaDevices.getDisplayMedia({
               video: {
                   cursor: 'always'
               }
           });
    
           // 獲取視頻軌道
           const videoTrack = screenCapture.getVideoTracks()[0];
           
           // 創(chuàng)建視頻元素以捕獲屏幕
           const videoElem = document.createElement('video');
           videoElem.srcObject = screenCapture;
           
           // 當(dāng)視頻加載完成后,繪制到畫布上
           videoElem.onloadedmetadata = () => {
               videoElem.play();
               
               // 設(shè)置畫布大小
               setCanvasSize();
               
               // 繪制視頻幀到畫布
               ctx.drawImage(videoElem, 0, 0, canvas.width, canvas.height);
               
               // 停止視頻軌道
               videoTrack.stop();
               
               // 顯示截圖容器
               screenshotContainer.style.display = 'block';
               isCapturing = true;
           };
       } catch (err) {
           console.error('截圖失敗:', err);
           alert('截圖失敗,請確保您已授予屏幕捕獲權(quán)限。');
       }
    }
    

    這里會請求屏幕捕獲權(quán)限并獲取屏幕內(nèi)容,這里可以選擇 瀏覽器標(biāo)簽頁、windows打開的窗口整個屏幕,確實可以獲取到瀏覽器之外的內(nèi)容。

  • 更新選擇區(qū)域

    function updateSelectionArea() {
          const width = Math.abs(endX - startX);
          const height = Math.abs(endY - startY);
          const left = Math.min(startX, endX);
          const top = Math.min(startY, endY);
    
          selectionArea.style.display = 'block';
          selectionArea.style.left = left + 'px';
          selectionArea.style.top = top + 'px';
          selectionArea.style.width = width + 'px';
          selectionArea.style.height = height + 'px';
    
          // 更新工具欄位置
          toolbar.style.display = 'flex';
          toolbar.style.left = (left + width + 5) + 'px';
          toolbar.style.top = (top + height + 5) + 'px';
    }
    
  • 確認(rèn)截圖(在這里獲取截圖結(jié)果)

    function confirmScreenshot() {
        if (!isCapturing) return;
    
        const width = Math.abs(endX - startX);
        const height = Math.abs(endY - startY);
        const left = Math.min(startX, endX);
        const top = Math.min(startY, endY);
    
        // 創(chuàng)建新畫布以保存選定區(qū)域
        const resultCanvas = document.createElement('canvas');
        resultCanvas.width = width;
        resultCanvas.height = height;
        const resultCtx = resultCanvas.getContext('2d');
    
        // 將選定區(qū)域繪制到新畫布
        resultCtx.drawImage(
            canvas,
            left, top, width, height,
            0, 0, width, height
        );
    
        // 在這里獲取截圖結(jié)果
        // 如果想生成成一個Base64url
        const base64Url = resultCanvas.toDataURL();
    	
    	// 如果想生成成一個File對象
    	const resultFile = dataURLtoFile(resultCanvas.toDataURL(), "截圖.png")
    	
        // 重置截圖狀態(tài)
        resetScreenshot();
    }
    
  • 將Base64數(shù)據(jù)轉(zhuǎn)換為File對象(不需要轉(zhuǎn)換結(jié)果為文件對象可以不寫這段)

    function dataURLtoFile(dataurl, filename) {
        // 將Base64數(shù)據(jù)拆分為MIME類型和實際數(shù)據(jù)
        const arr = dataurl.split(',');
        const mime = arr[0].match(/:(.*?);/)[1]; // 獲取MIME類型
        const bstr = atob(arr[1]); // 解碼Base64數(shù)據(jù)
        let n = bstr.length;
        const u8arr = new Uint8Array(n);
    
        // 將解碼后的數(shù)據(jù)轉(zhuǎn)換為Uint8Array
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
    
        // 創(chuàng)建并返回File對象
        return new File([u8arr], filename, { type: mime });
    }
    
  • 取消截圖

    function cancelScreenshot() {
        resetScreenshot();
    }
    
  • 重置截圖狀態(tài)

    function resetScreenshot() {
       isCapturing = false;
       isSelecting = false;
       selectionArea.style.display = 'none';
       toolbar.style.display = 'none';
       screenshotContainer.style.display = 'none';
       ctx.clearRect(0, 0, canvas.width, canvas.height);
    }
    
  • 各類監(jiān)聽事件

    // 事件監(jiān)聽器
    startButton.addEventListener('click', startScreenshot);
    confirmButton.addEventListener('click', confirmScreenshot);
    cancelButton.addEventListener('click', cancelScreenshot);
    
    // 鼠標(biāo)事件處理
    canvas.addEventListener('mousedown', function(e) {
        if (!isCapturing) return;
    
        isSelecting = true;
        startX = e.clientX;
        startY = e.clientY;
        endX = e.clientX;
        endY = e.clientY;
        updateSelectionArea();
    });
    
    canvas.addEventListener('mousemove', function(e) {
        if (!isSelecting) return;
    
        endX = e.clientX;
        endY = e.clientY;
        updateSelectionArea();
    });
    
    canvas.addEventListener('mouseup', function() {
        isSelecting = false;
    });
    
    // 窗口大小改變時重新設(shè)置畫布大小
    window.addEventListener('resize', function() {
        if (isCapturing) {
            setCanvasSize();
        }
    });
    
  • 鍵盤快捷鍵(不需要可以不用)

    // 鍵盤快捷鍵
    document.addEventListener('keydown', function(e) {
        // Alt + A 開始截圖
        if (e.altKey && e.key === 'a') {
            e.preventDefault();
            startScreenshot();
        }
        
        // Enter 確認(rèn)截圖
        if (e.key === 'Enter' && isCapturing) {
            confirmScreenshot();
        }
        
        // Esc 取消截圖
        if (e.key === 'Escape' && isCapturing) {
            cancelScreenshot();
        }
    });
    

完整代碼

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>截圖</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            font-family: 'Microsoft YaHei', sans-serif;
            background-color: #f5f5f5;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            overflow: hidden;
        }

        .container {
            text-align: center;
            background-color: white;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            max-width: 800px;
            width: 100%;
        }

        .button {
            background-color: #12B7F5;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.3s;
            margin-top: 10px;
        }

        .button:hover {
            background-color: #0E9AD7;
        }

        #screenshot-container {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 9999;
        }

        #screenshot-canvas {
            position: absolute;
            top: 0;
            left: 0;
            cursor: crosshair;
        }

        .selection-area {
            position: absolute;
            border: 2px dashed #12B7F5;
            background-color: rgba(18, 183, 245, 0.1);
            pointer-events: none;
        }

        .toolbar {
            position: absolute;
            background-color: white;
            border-radius: 4px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
            padding: 5px;
            display: flex;
            gap: 5px;
        }

        .toolbar button {
            background-color: #12B7F5;
            color: white;
            border: none;
            padding: 5px 10px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
        }

        .toolbar button:hover {
            background-color: #0E9AD7;
        }
    </style>
</head>
<body>
    <div class="container">
        <button id="start-screenshot" class="button">開始截圖</button>
    </div>

    <div id="screenshot-container">
        <canvas id="screenshot-canvas"></canvas>
        <div class="selection-area" id="selection-area" style="display: none;"></div>
        <div class="toolbar" id="screenshot-toolbar" style="display: none;">
            <button id="confirm-screenshot">確認(rèn)</button>
            <button id="cancel-screenshot">取消</button>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            // 元素引用
            const startButton = document.getElementById('start-screenshot');
            const screenshotContainer = document.getElementById('screenshot-container');
            const canvas = document.getElementById('screenshot-canvas');
            const ctx = canvas.getContext('2d');
            const selectionArea = document.getElementById('selection-area');
            const toolbar = document.getElementById('screenshot-toolbar');
            const confirmButton = document.getElementById('confirm-screenshot');
            const cancelButton = document.getElementById('cancel-screenshot');

            // 截圖狀態(tài)
            let isCapturing = false;
            let isSelecting = false;
            let startX = 0;
            let startY = 0;
            let endX = 0;
            let endY = 0;
            let screenCapture = null;

            // 設(shè)置畫布大小
            function setCanvasSize() {
                canvas.width = window.innerWidth;
                canvas.height = window.innerHeight;
            }

            // 開始截圖
            async function startScreenshot() {
                try {
                    // 請求屏幕捕獲
                    screenCapture = await navigator.mediaDevices.getDisplayMedia({
                        video: {
                            cursor: 'always'
                        }
                    });

                    // 獲取視頻軌道
                    const videoTrack = screenCapture.getVideoTracks()[0];
                    
                    // 創(chuàng)建視頻元素以捕獲屏幕
                    const videoElem = document.createElement('video');
                    videoElem.srcObject = screenCapture;
                    
                    // 當(dāng)視頻加載完成后,繪制到畫布上
                    videoElem.onloadedmetadata = () => {
                        videoElem.play();
                        
                        // 設(shè)置畫布大小
                        setCanvasSize();
                        
                        // 繪制視頻幀到畫布
                        ctx.drawImage(videoElem, 0, 0, canvas.width, canvas.height);
                        
                        // 停止視頻軌道
                        videoTrack.stop();
                        
                        // 顯示截圖容器
                        screenshotContainer.style.display = 'block';
                        isCapturing = true;
                    };
                } catch (err) {
                    console.error('截圖失敗:', err);
                    alert('截圖失敗,請確保您已授予屏幕捕獲權(quán)限。');
                }
            }

            // 更新選擇區(qū)域
            function updateSelectionArea() {
                const width = Math.abs(endX - startX);
                const height = Math.abs(endY - startY);
                const left = Math.min(startX, endX);
                const top = Math.min(startY, endY);

                selectionArea.style.display = 'block';
                selectionArea.style.left = left + 'px';
                selectionArea.style.top = top + 'px';
                selectionArea.style.width = width + 'px';
                selectionArea.style.height = height + 'px';

                // 更新工具欄位置
                toolbar.style.display = 'flex';
                toolbar.style.left = (left + width + 5) + 'px';
                toolbar.style.top = (top + height + 5) + 'px';
            }

            // 將Base64數(shù)據(jù)轉(zhuǎn)換為File對象
            function dataURLtoFile(dataurl, filename) {
                // 將Base64數(shù)據(jù)拆分為MIME類型和實際數(shù)據(jù)
                const arr = dataurl.split(',');
                const mime = arr[0].match(/:(.*?);/)[1]; // 獲取MIME類型
                const bstr = atob(arr[1]); // 解碼Base64數(shù)據(jù)
                let n = bstr.length;
                const u8arr = new Uint8Array(n);

                // 將解碼后的數(shù)據(jù)轉(zhuǎn)換為Uint8Array
                while (n--) {
                    u8arr[n] = bstr.charCodeAt(n);
                }

                // 創(chuàng)建并返回File對象
                return new File([u8arr], filename, { type: mime });
            }

            // 確認(rèn)截圖
            function confirmScreenshot() {
                if (!isCapturing) return;

                const width = Math.abs(endX - startX);
                const height = Math.abs(endY - startY);
                const left = Math.min(startX, endX);
                const top = Math.min(startY, endY);

                // 創(chuàng)建新畫布以保存選定區(qū)域
                const resultCanvas = document.createElement('canvas');
                resultCanvas.width = width;
                resultCanvas.height = height;
                const resultCtx = resultCanvas.getContext('2d');

                // 將選定區(qū)域繪制到新畫布
                resultCtx.drawImage(
                    canvas,
                    left, top, width, height,
                    0, 0, width, height
                );

                // 在這里獲取截圖結(jié)果
                // 如果想生成成一個Base64url
                const base64Url = resultCanvas.toDataURL();
                
                // 如果想生成成一個File對象
                const resultFile = dataURLtoFile(resultCanvas.toDataURL(), "截圖.png")

                // 重置截圖狀態(tài)
                resetScreenshot();
            }

            // 取消截圖
            function cancelScreenshot() {
                resetScreenshot();
            }

            // 重置截圖狀態(tài)
            function resetScreenshot() {
                isCapturing = false;
                isSelecting = false;
                selectionArea.style.display = 'none';
                toolbar.style.display = 'none';
                screenshotContainer.style.display = 'none';
                ctx.clearRect(0, 0, canvas.width, canvas.height);
            }

            // 事件監(jiān)聽器
            startButton.addEventListener('click', startScreenshot);
            confirmButton.addEventListener('click', confirmScreenshot);
            cancelButton.addEventListener('click', cancelScreenshot);

            // 鼠標(biāo)事件處理
            canvas.addEventListener('mousedown', function(e) {
                if (!isCapturing) return;

                isSelecting = true;
                startX = e.clientX;
                startY = e.clientY;
                endX = e.clientX;
                endY = e.clientY;
                updateSelectionArea();
            });

            canvas.addEventListener('mousemove', function(e) {
                if (!isSelecting) return;

                endX = e.clientX;
                endY = e.clientY;
                updateSelectionArea();
            });

            canvas.addEventListener('mouseup', function() {
                isSelecting = false;
            });

            // 鍵盤快捷鍵
            document.addEventListener('keydown', function(e) {
                // Alt + A 開始截圖
                if (e.altKey && e.key === 'a') {
                    e.preventDefault();
                    startScreenshot();
                }
                
                // Enter 確認(rèn)截圖
                if (e.key === 'Enter' && isCapturing) {
                    confirmScreenshot();
                }
                
                // Esc 取消截圖
                if (e.key === 'Escape' && isCapturing) {
                    cancelScreenshot();
                }
            });

            // 窗口大小改變時重新設(shè)置畫布大小
            window.addEventListener('resize', function() {
                if (isCapturing) {
                    setCanvasSize();
                }
            });
        });
    </script>
</body>
</html>

總結(jié)

姑且算是實現(xiàn)了這個需求,但是實現(xiàn)效果并不是很理想,只能說僅供參考吧

到此這篇關(guān)于用JavaScript實現(xiàn)瀏覽器截圖功能的文章就介紹到這了,更多相關(guān)JS瀏覽器截圖功能內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Bootstrap輪播插件中圖片變形的終極解決方案 使用jqthumb.js

    Bootstrap輪播插件中圖片變形的終極解決方案 使用jqthumb.js

    這篇文章主要介紹了Bootstrap輪播插件中圖片變形的終極解決方案,使用jqthumb.js,感興趣的小伙伴們可以參考一下
    2016-07-07
  • 深入理解JavaScript系列(29):設(shè)計模式之裝飾者模式詳解

    深入理解JavaScript系列(29):設(shè)計模式之裝飾者模式詳解

    這篇文章主要介紹了深入理解JavaScript系列(29):設(shè)計模式之裝飾者模式詳解,裝飾者用用于包裝同接口的對象,不僅允許你向方法添加行為,而且還可以將方法設(shè)置成原始對象調(diào)用(例如裝飾者的構(gòu)造函數(shù)),需要的朋友可以參考下
    2015-03-03
  • js實現(xiàn)簡單的可切換選項卡效果

    js實現(xiàn)簡單的可切換選項卡效果

    這篇文章主要介紹了js實現(xiàn)簡單的可切換選項卡效果的方法,涉及javascript操作css樣式實現(xiàn)切換選項卡的技巧,非常具有實用價值,需要的朋友可以參考下
    2015-04-04
  • 不使用XMLHttpRequest實現(xiàn)異步加載 Iframe和script

    不使用XMLHttpRequest實現(xiàn)異步加載 Iframe和script

    運用Iframe和script可以實現(xiàn)簡單的異步加載,沒有使用XMLHttpRequest,需要的朋友可以參考下
    2012-10-10
  • 如何確保JavaScript的執(zhí)行順序 之實戰(zhàn)篇

    如何確保JavaScript的執(zhí)行順序 之實戰(zhàn)篇

    我曾在文章《如何在多個頁面使用同一個HTML片段 - 續(xù)》的最后提到JavaScript順序執(zhí)行的特性。雖然現(xiàn)代瀏覽器可以并行的下載JavaScript(部分瀏覽器),但考慮到JavaScript的依賴關(guān)系,他們的執(zhí)行依然是按照引入順序進(jìn)行的。
    2011-03-03
  • HTML+JavaScript實現(xiàn)掃雷小游戲

    HTML+JavaScript實現(xiàn)掃雷小游戲

    這篇文章主要為大家詳細(xì)介紹了HTML+JavaScript實現(xiàn)掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • 原生js實現(xiàn)日期聯(lián)動

    原生js實現(xiàn)日期聯(lián)動

    日期聯(lián)動算是一個比較常見的功能了,隨便度娘一下,你就能找到N多代碼,今天給大家介紹的是個人比較常用,代碼很簡潔,高效,這里推擠給大家。
    2015-01-01
  • javascript實現(xiàn)手動點贊效果

    javascript實現(xiàn)手動點贊效果

    這篇文章主要為大家詳細(xì)介紹了javascript實現(xiàn)手動點贊效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • 判定對象是否為window的js代碼

    判定對象是否為window的js代碼

    這是一個非常有趣的題目。我們先從Object.prototype.toString入手,看能否解決它。
    2010-02-02
  • JS跨域總結(jié)

    JS跨域總結(jié)

    JS跨域總結(jié),主要是解決js中跨域訪問的我問題
    2012-08-08

最新評論