Làm cách nào để chụp ảnh màn hình của div với JavaScript?


175

Tôi đang xây dựng một thứ gọi là "Câu đố HTML". Nó hoàn toàn chạy trên JavaScript và nó khá tuyệt.

Cuối cùng, một hộp kết quả bật lên có nội dung "Kết quả của bạn:" và nó cho biết họ đã mất bao nhiêu thời gian, bao nhiêu phần trăm và bao nhiêu câu hỏi họ nhận được ngay từ 10. Tôi muốn có một nút nói "Chụp kết quả" và bằng cách nào đó hãy chụp ảnh màn hình hoặc một cái gì đó của div, sau đó chỉ hiển thị hình ảnh được chụp trên trang nơi họ có thể nhấp chuột phải và "Lưu hình ảnh dưới dạng".

Tôi thực sự rất thích làm điều này để họ có thể chia sẻ kết quả của họ với người khác. Tôi không muốn họ "sao chép" kết quả vì họ có thể dễ dàng thay đổi điều đó. Nếu họ thay đổi những gì nó nói trong hình ảnh, oh tốt.

Có ai biết một cách để làm điều này hoặc một cái gì đó tương tự?


2
Có một cái nhìn tại ph Phantomjs.org . Sử dụng nó, bạn có thể tạo một hình ảnh đầy đủ của trang HTML trên máy chủ và cung cấp cho người dùng một liên kết để tải xuống.
Joshua

Nội dung HTML bài viết hay để chuyển đổi hình ảnh và tải về codepedia.info/ Từ
Satinder singh

Câu trả lời:


98

Không, tôi không biết cách 'ảnh chụp màn hình' một yếu tố, nhưng những gì bạn có thể làm là vẽ kết quả bài kiểm tra thành một yếu tố canvas, sau đó sử dụng chức năng HTMLCanvasElementcủa đối tượng toDataURLđể lấy data:URI với nội dung của hình ảnh.

Khi bài kiểm tra kết thúc, làm điều này:

var c = document.getElementById('the_canvas_element_id');
var t = c.getContext('2d');
/* then use the canvas 2D drawing functions to add text, etc. for the result */

Khi người dùng nhấp vào "Chụp", hãy làm điều này:

window.open('', document.getElementById('the_canvas_element_id').toDataURL());

Điều này sẽ mở một tab hoặc cửa sổ mới với 'ảnh chụp màn hình', cho phép người dùng lưu nó. Không có cách nào để gọi một hộp thoại 'lưu dưới dạng', vì vậy đây là cách tốt nhất bạn có thể làm theo ý kiến ​​của tôi.


Cảm ơn!! Tôi không biết gì về vải, nhưng tôi sẽ học nó. Làm cách nào để sử dụng hiệu ứng vẽ Canvas 2D? Bạn có thể giúp tôi với điều này? Cám ơn rất nhiều! :)
Nathan

5
Hãy thử tài liệu của Mozilla, nó thực sự khá dễ thực hiện: developer.mozilla.org/en/canvas_tutorial
Delan Azabani

Thay vì mở nó trong một cửa sổ / tab mới, tôi có thể mở nó trong hộp thoại nội tuyến không? (Giống như plugin hộp đèn Fancybox?)
Nathan

Vâng, bạn có thể có một hộp thoại nội tuyến với một imgmà có nó srcthiết lập để các data:URI. Tuy nhiên, điều đó không thực sự cần thiết - bạn chỉ có thể đặt canvaschính nó vào hộp thoại nội tuyến; Người dùng có thể nhấp chuột phải vào nó và lưu trạng thái hiện tại dưới dạng hình ảnh.
Delan Azabani

Cảm ơn :) Tôi có thể sử dụng phiên bản hình ảnh để họ có thể nhấp chuột phải và nhấp vào "lưu hình ảnh dưới dạng"
Nathan

89

Đây là bản mở rộng câu trả lời của @ Dathan , sử dụng html2canvasFileSaver.js .

$(function() { 
    $("#btnSave").click(function() { 
        html2canvas($("#widget"), {
            onrendered: function(canvas) {
                theCanvas = canvas;


                canvas.toBlob(function(blob) {
                    saveAs(blob, "Dashboard.png"); 
                });
            }
        });
    });
});

Khối mã này chờ nút có id btnSaveđược nhấp. Khi có, nó chuyển đổi widgetdiv thành một phần tử canvas và sau đó sử dụng giao diện SaveS () FileSaver (thông qua FileSaver.js trong các trình duyệt không hỗ trợ nó) để lưu div dưới dạng hình ảnh có tên "Dashboard.png".

Một ví dụ về công việc này có sẵn tại fiddle này .


7
Tôi cần thêm các tham chiếu đến: html2canvas, filesaver, blob, canvas-toBlob. Sau đó nó hoạt động. Cảm ơn!
sirthomas

1
Tuyệt vời, đây sẽ là câu trả lời được chấp nhận. Đơn giản cắm n chơi.
rgshenoy

Bạn có biết làm thế nào điều này sẽ làm việc với ba.js? Tôi có một div mà trình kết xuất / canvas của ba.js nằm trong (renderer.domEuity), và sau đó div trên đầu trang đó. Tôi muốn chụp ảnh DIV cha mẹ và chụp mọi thứ? Điều này có thể không? Cảm ơn!
Rankinstudio

1
Bạn có thể tránh hình ảnh xuất hiện trong DOM của bạn? Nó không thể đi để tải về ngay lập tức?
kulan

1
Điều này làm việc rất tốt cho tôi trong lần thử đầu tiên, và thậm chí trông giống như kiểu CSS gốc, v.v ... Chính xác đến mức đáng kinh ngạc. Khá nhiều ảnh chụp màn hình ảo với mức độ chính xác này. Tôi đã sử dụng CDN cho 2 thư viện mà tôi phải thêm: <! - html2canvas -> <script src = " cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/ tựa > <! - filesaver - > <script src = " cdn.jsdelivr.net/npm/file-saver@2.0.2/dist/ Kẻ >
OG Sean

13

Sau nhiều giờ nghiên cứu, cuối cùng tôi cũng tìm được giải pháp chụp ảnh màn hình của một yếu tố, ngay cả khi origin-cleanFLAG được đặt (để ngăn XSS), đó là lý do tại sao bạn thậm chí có thể chụp ví dụ Google Maps (trong trường hợp của tôi). Tôi đã viết một chức năng phổ quát để có được một ảnh chụp màn hình. Điều duy nhất bạn cần ngoài ra là thư viện html2canvas ( https://html2canvas.hertzen.com/ ).

Thí dụ:

getScreenshotOfElement($("div#toBeCaptured").get(0), 0, 0, 100, 100, function(data) {
    // in the data variable there is the base64 image
    // exmaple for displaying the image in an <img>
    $("img#captured").attr("src", "data:image/png;base64,"+data);
});

Hãy ghi nhớ console.log()alert()giành được đầu ra tạo ra nếu kích thước của hình ảnh là tuyệt vời.

Chức năng:

function getScreenshotOfElement(element, posX, posY, width, height, callback) {
    html2canvas(element, {
        onrendered: function (canvas) {
            var context = canvas.getContext('2d');
            var imageData = context.getImageData(posX, posY, width, height).data;
            var outputCanvas = document.createElement('canvas');
            var outputContext = outputCanvas.getContext('2d');
            outputCanvas.width = width;
            outputCanvas.height = height;

            var idata = outputContext.createImageData(width, height);
            idata.data.set(imageData);
            outputContext.putImageData(idata, 0, 0);
            callback(outputCanvas.toDataURL().replace("data:image/png;base64,", ""));
        },
        width: width,
        height: height,
        useCORS: true,
        taintTest: false,
        allowTaint: false
    });
}

nơi bạn đã xác định hàm html2canvas
Bharathi

Tôi đã tích hợp thư viện html2canvas (xem liên kết trong bài viết của mình) trước khi đạt được hàm getSc MuffOfEuity (). Ví dụ với <script> -tag. Chỉ cần tải về html2canvas và sao chép nó vào dự án của bạn.
cam01

@ cam01 - Tôi vẫn chưa thể chụp làn đường trên bản đồ google. Điều này chỉ chụp màn hình nút phóng to và thu nhỏ, Bản đồ và văn bản vệ tinh. bạn có thể vui lòng giúp đỡ để chụp bản đồ đầy đủ. Cảm ơn
Farhan Sahibole

7

Nếu bạn muốn có hộp thoại "Lưu dưới dạng", chỉ cần chuyển hình ảnh vào tập lệnh php, thêm tiêu đề thích hợp

Ví dụ tập lệnh "tất cả trong một" script.php

<?php if(isset($_GET['image'])):
    $image = $_GET['image'];

    if(preg_match('#^data:image/(.*);base64,(.*)$#s', $image, $match)){
        $base64 = $match[2];
        $imageBody = base64_decode($base64);
        $imageFormat = $match[1];

        header('Content-type: application/octet-stream');
        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Cache-Control: private", false); // required for certain browsers
        header("Content-Disposition: attachment; filename=\"file.".$imageFormat."\";" ); //png is default for toDataURL
        header("Content-Transfer-Encoding: binary");
        header("Content-Length: ".strlen($imageBody));
        echo $imageBody;
    }
    exit();
endif;?>

<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js?ver=1.7.2'></script>
<canvas id="canvas" width="300" height="150"></canvas>
<button id="btn">Save</button>
<script>
    $(document).ready(function(){
        var canvas = document.getElementById('canvas');
        var oCtx = canvas.getContext("2d");
        oCtx.beginPath();
        oCtx.moveTo(0,0);
        oCtx.lineTo(300,150);
        oCtx.stroke();

        $('#btn').on('click', function(){
            // opens dialog but location doesnt change due to SaveAs Dialog
            document.location.href = '/script.php?image=' + canvas.toDataURL();
        });
    });
</script>

4

Một cách khác là sử dụng API JavaScript của GrabzIt, tất cả những gì bạn cần làm là vượt qua bộ chọn CSS của div bạn muốn chụp. Sau đó, nó sẽ tạo ra một ảnh chụp màn hình của div đó.

<script type="text/javascript" src="grabzit.min.js"></script>
<script type="text/javascript">
GrabzIt("YOUR APPLICATION KEY").ConvertURL("http://www.example.com/quiz.html",
{"target": "#results", "bheight": -1, "height": -1, "width": -1}).Create();
</script>

Có nhiều ví dụ ở đây giải quyết cách nắm bắt các yếu tố HTML . Để tiết lộ đầy đủ, tôi là người tạo API.


Nó không phải là một phần mềm miễn phí
Amirhossein Tarmast

3

Bạn không thể chụp ảnh màn hình: sẽ là một rủi ro bảo mật vô trách nhiệm khi để bạn làm như vậy. Tuy nhiên, bạn có thể:

  • Làm những thứ phía máy chủ và tạo một hình ảnh
  • Vẽ một cái gì đó tương tự như Canvas và hiển thị nó thành hình ảnh (trong trình duyệt hỗ trợ nó)
  • Sử dụng một số thư viện vẽ khác để vẽ trực tiếp lên hình ảnh (chậm, nhưng sẽ hoạt động trên mọi trình duyệt)

Cảm ơn! Tôi sẽ đi với khung vẽ, vì tôi không biết về bất kỳ "thư viện vẽ" nào và tôi cũng không biết làm thế nào để làm điều đó. Tôi cũng không giỏi về canvas nhưng tôi sẽ thử.
Nathan

2
Xin lỗi tôi phải nhận xét điều này vì nó xuất phát từ google nhưng WTF "rủi ro bảo mật vô trách nhiệm" tôi có thể hỏi tại sao, nếu bạn để javascript chụp ảnh màn hình hoặc chụp trong các dây đã cho và trả lại dữ liệu được mã hóa BASE64 của nó dưới dạng chuỗi không có vấn đề bảo mật
Barkermn01

@MartinBarker Tôi có thể (ví dụ) kéo lên trang Facebook của ai đó trong iframe và sau đó chụp màn hình. Thông thường, iframe chéo trang không phải là một phần của DOM có thể truy cập để ngăn XSS, nhưng nhà cung cấp trình duyệt sẽ khó ngăn chặn nó hơn trong trường hợp như vậy.
bgw

2
@MartinBarker Javascript có thể cung cấp dữ liệu cho nguồn độc hại mà không cần người dùng nhận thấy, trong khi "màn hình in" được kiểm soát bởi người dùng và không phải là một số trang web không đáng tin cậy.
bgw

2
Thật là một nhịp đập lên. @PiPeep, Nếu một trang web có thể tải lên iFrame của Facebook, thì đã có sự cô lập, tại sao không mở rộng sự cô lập như vậy với API ảnh chụp màn hình? ví dụ. Div.ToPNG (), trong đó iFrame đã nói ở trên được loại bỏ? Đây không phải là một rủi ro bảo mật vô trách nhiệm, nó chỉ không có tích hợp sẵn và không ai đã giải quyết các vấn đề bảo mật / quyền riêng tư "tiềm năng" trong việc phát triển API ảnh chụp màn hình được tích hợp như vậy. Nó sẽ vô cùng hữu ích cho vô số trường hợp sử dụng, chẳng hạn như hỗ trợ các ứng dụng web mạng nội bộ chẳng hạn.
Todd

3
var shot1=imagify($('#widget')[0], (base64) => {
  $('img.screenshot').attr('src', base64);
});

Hãy xem gói htmlshot , sau đó, kiểm tra sâu phần phía máy khách :

npm install htmlshot

dự án htmlshot này vẫn được duy trì? Liên kết github từ npm không còn tồn tại. Có một trang web khác cho nó?
whatsTheDiff

@whatsTheDiff :: cung cấp cho tôi yêu cầu của bạn và chắc chắn rằng tôi sẽ giúp bạn. Vì vậy, tôi là tác giả của thư viện này.
Abdennour TOUMI

2
Cảm ơn @ abdennour-toumi. Tôi vừa thực hiện cài đặt npm để xem qua mã. Có vẻ như nó đang sử dụng html2canvas mà tôi đã thử và đang gặp sự cố trong IE và do sự phức tạp của SVG và trang của tôi. Vì vậy, có vẻ như thư viện này sẽ không giúp tôi về vấn đề đó.
whatsTheDiff

4
Khách hàng của bạn phải tránh IE .. nói với họ điều đó!
Abdennour TOUMI

1
<script src="/assets/backend/js/html2canvas.min.js"></script>


<script>
    $("#download").on('click', function(){
        html2canvas($("#printform"), {
            onrendered: function (canvas) {
                var url = canvas.toDataURL();

                var triggerDownload = $("<a>").attr("href", url).attr("download", getNowFormatDate()+"电子签名详细信息.jpeg").appendTo("body");
                triggerDownload[0].click();
                triggerDownload.remove();
            }
        });
    })
</script>

bảng báo giá


1

Thật đơn giản, bạn có thể sử dụng mã này để chụp ảnh màn hình của khu vực cụ thể mà bạn phải xác định id id trong html2canvas. Tôi đang sử dụng ở đây 2 div-:

div id = "xe hơi"
div id = "chartContainer"
nếu bạn muốn chụp chỉ chiếc xe sau đó sử dụng xe tôi chụp ở đây xe duy nhất bạn có thể thay đổi chartContainer để chụp đồ thị html2canvas ($ ( '#car') sao chép và dán mã này

<html>
    <head>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.5/jspdf.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">
<script>
    window.onload = function () {
    
    var chart = new CanvasJS.Chart("chartContainer", {
        animationEnabled: true,
        theme: "light2",
        title:{
            text: "Simple Line Chart"
        },
        axisY:{
            includeZero: false
        },
        data: [{        
            type: "line",       
            dataPoints: [
                { y: 450 },
                { y: 414},
                { y: 520, indexLabel: "highest",markerColor: "red", markerType: "triangle" },
                { y: 460 },
                { y: 450 },
                { y: 500 },
                { y: 480 },
                { y: 480 },
                { y: 410 , indexLabel: "lowest",markerColor: "DarkSlateGrey", markerType: "cross" },
                { y: 500 },
                { y: 480 },
                { y: 510 }

            ]
        }]
    });
    chart.render();
    
    }
</script>
</head>

<body bgcolor="black">
<div id="wholebody">  
<a href="javascript:genScreenshotgraph()"><button style="background:aqua; cursor:pointer">Get Screenshot of Cars onl </button> </a>

<div id="car" align="center">
    <i class="fa fa-car" style="font-size:70px;color:red;"></i>
    <i class="fa fa-car" style="font-size:60px;color:red;"></i>
    <i class="fa fa-car" style="font-size:50px;color:red;"></i>
    <i class="fa fa-car" style="font-size:20px;color:red;"></i>
    <i class="fa fa-car" style="font-size:50px;color:red;"></i>
    <i class="fa fa-car" style="font-size:60px;color:red;"></i>
    <i class="fa fa-car" style="font-size:70px;color:red;"></i>
</div>
<br>
<div id="chartContainer" style="height: 370px; width: 100%;"></div>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>

<div id="box1">
</div>
</div>>
</body>

<script>

function genScreenshotgraph() 
{
    html2canvas($('#car'), {
        
      onrendered: function(canvas) {

        var imgData = canvas.toDataURL("image/jpeg");
        var pdf = new jsPDF();
        pdf.addImage(imgData, 'JPEG', 0, 0, -180, -180);
        pdf.save("download.pdf");
        
      
      
      }
     });

}

</script>

</html>


1
Tại sao jQuery được bao gồm hai lần và tại sao UI UI được bao gồm? Thành thật mà nói, jQuery hoàn toàn không cần ở đây từ những gì tôi có thể nói. document.getElementById('car')hoặcdocument.querySelector('#car')
Nathan

thực sự tôi đang làm việc trong dự án của tôi Vì vậy, tôi chỉ quên về việc loại bỏ thư viện và không có gì.
Rudra Pratap Singh

0

Theo như tôi biết bạn không thể làm điều đó, tôi có thể sai. Tuy nhiên, tôi sẽ làm điều này với php, tạo JPEG bằng các hàm tiêu chuẩn php và sau đó hiển thị hình ảnh, không phải là một công việc rất khó khăn, tuy nhiên phụ thuộc vào mức độ hào nhoáng của nội dung của DIV


OP không bao giờ gợi ý rằng anh ta đang sử dụng xử lý phía máy chủ, mặc dù nếu có, điều này sẽ ổn.
Delan Azabani

Vâng, tôi không thể sử dụng công cụ phía máy chủ không may. Tôi có thể sẽ đi với một trong những câu trả lời ở trên. Nhưng cảm ơn! :)
Nathan

-3

Theo như tôi biết thì không thể với javascript.

Những gì bạn có thể làm cho mỗi kết quả tạo ảnh chụp màn hình, lưu nó ở đâu đó và trỏ người dùng khi nhấp vào lưu kết quả. (Tôi đoán không có kết quả nào chỉ là 10 nên không phải là vấn đề lớn để tạo ra hình ảnh 10 jpeg kết quả)


Cảm ơn đã trả lời :) Bạn nói đúng! Tôi chỉ có thể tạo 10 hình ảnh JPG về kết quả và sau đó khi họ nhấp vào nút, nó sẽ hiển thị hình ảnh để họ lưu lại. Vấn đề duy nhất là khi họ bắt đầu bài kiểm tra, họ phải nhập tên của họ và tôi hiển thị nó qua bài kiểm tra, và ở cuối hộp kết quả, nó hiển thị tên của họ và nó nói một bình luận như "Trở nên tốt hơn" vv Tôi sẽ không thể đặt tên của họ trong hình ảnh hoặc tôi sẽ?
Nathan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.