JavaScript로 div의 스크린 샷을 만드는 방법은 무엇입니까?


175

"HTML 퀴즈"라는 것을 만들고 있습니다. JavaScript에서 완전히 실행되었으며 꽤 멋집니다.

마지막에 "Your Results :"라는 결과 상자가 나타나고 소요 시간, 소요 비율 및 10 개 중 몇 가지 질문이 표시되는지 나타냅니다. 버튼이 있습니다. "결과 캡처"를하여 어떻게 든 스크린 샷이나 div를 캡처 한 다음 페이지에서 캡처 한 이미지를 마우스 오른쪽 단추로 클릭하고 "다른 이름으로 이미지 저장"을 표시하십시오.

나는 그들이 다른 사람들과 결과를 공유 할 수 있도록 정말로 이것을하고 싶습니다. 나는 그들이 쉽게 변경할 수 있기 때문에 결과를 "복사"하기를 원하지 않습니다. 그들이 이미지에서 말하는 것을 바꾸면, 오 잘.

누구든지 이것을하거나 비슷한 것을하는 방법을 알고 있습니까?


2
phantomjs.org를 살펴 보십시오 . 이를 사용하면 서버 측에서 HTML 페이지의 전체 이미지를 생성하고 사용자에게 다운로드 링크를 제공 할 수 있습니다.
여호수아

멋진 기사 HTML 컨텐츠 이미지 변환 및 codepedia.info/…
Satinder singh

답변:


98

아니요, 요소를 '스크린 샷'하는 방법을 모르지만 퀴즈 결과를 캔버스 요소에 그린 다음 HTMLCanvasElement객체의 toDataURL함수를 data:사용하여 이미지 내용 이 포함 된 URI 를 얻는 것이 좋습니다.

퀴즈가 끝나면 다음과 같이하십시오.

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 */

사용자가 "캡처"를 클릭하면 다음과 같이하십시오.

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

그러면 '스크린 샷'이 포함 된 새 탭 또는 창이 열리고 사용자가 저장할 수 있습니다. 일종의 '다른 이름으로 저장'대화 상자를 호출 할 수있는 방법이 없으므로 이것이 내 의견으로는 최선의 방법입니다.


감사!! 나는 캔버스에 대해 아무것도 모른다. 그러나 나는 그것을 배울 것이다. Canvas 2D 그리기 효과를 어떻게 사용합니까? 이것 좀 도와 주실 래요? 정말 고마워! :)
Nathan

5
모질라의 문서를
보아라

새 창 / 탭에서 열지 않고 인라인 대화 상자에서 열 수 있습니까? (Fancybox 라이트 박스 플러그인처럼?)
Nathan

그래, 당신은과 인라인 대화 상자 가질 수 img는있다가 src받는 일련의 data:URI를. 그러나 실제로는 필요하지 않습니다 canvas. 인라인 대화 상자에 입력하면 됩니다. 사용자는 마우스 오른쪽 버튼을 클릭하여 현재 상태를 이미지로 저장할 수 있습니다.
Delan Azabani

고마워 :) 나는 이미지 버전을 사용할 수 있도록 마우스 오른쪽 버튼을 클릭하고 "다른 이름으로 이미지 저장"을 클릭 할 수 있습니다
Nathan

89

이것은 html2canvasFileSaver.js를 사용하여 @Dathan답변을 확장 한 것입니다 .

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


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

이 코드 블록은 ID btnSave가있는 버튼이 클릭 될 때까지 기다립니다 . 이 경우 widgetdiv를 캔버스 요소 로 변환 한 다음 saveAs () FileSaver 인터페이스 (기본적으로 지원하지 않는 브라우저의 FileSaver.js를 통해)를 사용하여 "Dashboard.png"라는 이미지로 div를 저장합니다.

이 작업의 예는이 바이올린 에서 사용할 수 있습니다 .


7
html2canvas, filesaver, blob, canvas-toBlob에 대한 참조를 추가해야했습니다. 그 후 그것은 효과가있었습니다. 감사!
sirthomas

1
멋진 답변입니다. 간단한 플러그 앤 플레이.
rgshenoy

이것이 three.js와 어떻게 작동하는지 알고 있습니까? three.js 렌더러 / 캔버스가 (renderer.domElement)에있는 div가 있고 그 위에 div가 있습니다. 부모 DIV의 스냅 샷을 찍고 모든 것을 캡처하고 싶습니까? 이게 가능해? 감사!
Rankinstudio

1
DOM에 이미지가 나타나는 것을 피할 수 있습니까? 바로 다운로드 할 수 없습니까?
쿨란

1
이것은 첫 번째 시도에서 나에게 효과적이었으며 심지어 원래 CSS 스타일링처럼 보입니다. 놀랍도록 정확합니다. 이 수준의 정확도를 가진 거의 가상 스크린 샷입니다. 추가해야하는 2 개의 라이브러리에 CDN을 사용했습니다 : <!-html2canvas-> <script src = " cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/… > <!-filesaver- > <script src = " cdn.jsdelivr.net/npm/file-saver@2.0.2/dist/… >
OG Sean

13

몇 시간의 연구 끝에 마침내 origin-cleanFLAG가 설정되어 있어도 (XSS를 방지하기 위해) 요소의 스크린 샷을 찍을 수있는 솔루션을 찾았습니다 . 스크린 샷을 얻는 범용 함수를 작성했습니다. 또한 필요한 것은 html2canvas 라이브러리 ( https://html2canvas.hertzen.com/ ) 뿐입니다 .

예:

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);
});

이미지의 크기가 크면 명심 console.log()하고 alert()출력을 생성하지 않습니다.

함수:

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
    });
}

html2canvas 함수를 정의한 위치
Bharathi

getScreenshotOfElement () 함수에 도달하기 전에 라이브러리 html2canvas (내 게시물의 링크 참조)를 통합했습니다. 예를 들어 <script> -tag를 사용하십시오. html2canvas를 다운로드하여 프로젝트에 복사하십시오.
orange01

@ orange01-여전히 Google지도의 거리 차선을 캡처 할 수 없습니다. 확대 / 축소 버튼,지도 및 위성 텍스트 만 스크린 샷으로 표시됩니다. 당신은 전체지도를 캡처 도와주세요? 감사합니다
Farhan Sahibole

7

"다른 이름으로 저장"대화 상자를 원한다면 PHP 헤더로 이미지를 전달하면 적절한 헤더가 추가됩니다.

"올인원"스크립트 예 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>

3

스크린 샷을 찍을 수는 없습니다. 그렇게하는 것은 무책임한 보안 위험입니다. 그러나 다음을 수행 할 수 있습니다.

  • 서버 측에서 작업하고 이미지 생성
  • Canvas와 비슷한 것을 그리고 그것을 지원하는 브라우저에서 이미지로 렌더링
  • 다른 그림 라이브러리를 사용하여 이미지에 직접 그리십시오 (느리지 만 모든 브라우저에서 작동합니다)

감사! "도서관"을 모르거나 그 방법을 알지 못하기 때문에 캔버스와 함께 갈 것입니다. 나는 캔버스를 잘하지 못하지만 시도 할 것입니다.
Nathan

2
죄송합니다 .Google에서 올렸을 때 이것을 언급해야하지만 WTF "무책임한 보안 위험"으로 인해 Javascript가 주어진 코드 내에서 스크린 샷이나 샷을 찍고 BASE64로 인코딩 된 데이터를 문자열로 반환하면 보안이 문제가됩니다.
Barkermn01

@MartinBarker 예를 들어 누군가의 Facebook 페이지를 iframe에서 가져온 다음 스크린 샷을 찍을 수 있습니다. 일반적으로 크로스 사이트 iframe은 XSS를 방지하기 위해 액세스 가능한 DOM의 일부가 아니지만 이러한 경우 브라우저 공급 업체가 중지하기가 훨씬 어렵습니다.
bgw

2
@MartinBarker Javascript는 사용자가 몰라도 데이터를 악성 소스에 제공 할 수 있지만 "인쇄 화면"은 사용자에 의해 제어되며 일부는 신뢰할 수없는 웹 사이트가 아닙니다.
bgw

2
이길. @ PiPeep, 웹 페이지가 Facebook의 iFrame을로드 할 수 있다면 이미 격리가 있습니다. 스크린 샷 API로 그러한 격리를 확장하지 않는 이유는 무엇입니까? 예. Div.ToPNG (), 위에서 언급 한 iFrame이 흰색으로 표시됩니까? 이는 무책임한 보안 위험이 아니며, 기본 제공 기능이 없으며, 내장 된 스크린 샷 API를 개발할 때 "잠재적 인"개인 정보 / 보안 문제를 해결 한 사람이 없습니다. 예를 들어 인트라넷 웹 응용 프로그램 지원과 같은 무수한 사용 사례에 매우 유용합니다.
Todd

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

htmlshot package 를 살펴본 다음 클라이언트 측 섹션 을 자세히 확인 하십시오.

npm install htmlshot

이 htmlshot 프로젝트가 계속 유지됩니까? npm의 github 링크가 여전히 존재하지 않는 것 같습니다. 다른 웹 사이트가 있습니까?
whatsTheDiff

@whatsTheDiff :: 나에게 요구 사항을 제공하고, 내가이 라이브러리의 저자이기 때문에 내가 당신을 도울 것임을 확신하십시오.
Abdennour TOUMI

2
감사합니다 @ abdennour-toumi. 방금 코드를 살펴보기 위해 npm 설치를 수행했습니다. 내가 시도하고 IE에서 문제가 있으며 SVG의 복잡성과 내 페이지의 복잡성으로 인해 html2canvas를 사용하고있는 것 같습니다. 따라서이 라이브러리는 그 점에서 도움이되지 않는 것 같습니다.
whatsTheDiff

4
고객은 IE를 피해야합니다.
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>

인용


1

이 코드를 사용하여 html2canvas에서 div id를 정의 해야하는 특정 영역의 스크린 샷을 캡처하는 것이 간단합니다. : 여기이 div- 사용하고

= "자동차"DIV id를
DIV ID = "chartContainer을"
당신은 차를 캡처 할 경우 다음 사용하는 차를 내가에만 변경할 수 있습니다 여기에 자동차 캡처 해요 chartContainer를 그래프 캡처 (($ html2canvas '#car') 이 코드를 복사하여 붙여 넣기

<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
jQuery가 두 번 포함 된 이유와 jQuery UI가 포함 된 이유는 무엇입니까? 솔직히 jQuery는 내가 말할 수있는 것에서 전혀 필요하지 않습니다. document.getElementById('car')또는document.querySelector('#car')
Nathan

실제로 나는 내 프로젝트에서 일하고 있습니다. 그래서 나는 단지 라이브러리를 제거하는 것을 잊고 아무것도 없습니다.
Rudra Pratap Singh

0

내가 아는 한, 내가 잘못했을 수도 있습니다. 그러나 PHP 로이 작업을 수행하고 PHP 표준 기능을 사용하여 JPEG를 생성 한 다음 이미지를 표시합니다. 매우 어려운 작업은 아니지만 DIV의 내용이 얼마나 화려한 지에 따라 다릅니다.


OP는 서버 측 처리를 사용한다고 제안하지는 않았지만 괜찮다면 괜찮을 것입니다.
Delan Azabani

네, 안타깝게도 서버 측은 사용할 수 없습니다. 아마 위의 답변 중 하나와 함께 갈 것입니다. 그러나 감사합니다! :)
Nathan

-3

내가 아는 한 자바 스크립트로는 불가능합니다.

모든 결과에 대해 수행 할 수있는 작업은 스크린 샷을 생성하고 어딘가에 저장 한 후 결과 저장을 클릭하면 사용자를 가리 킵니다. (결과는 10에 불과하므로 10 jpeg 이미지 결과를 만드는 데 큰 도움이되지는 않습니다)


답변 주셔서 감사합니다 :) 당신이 맞아요! 결과의 JPG 이미지 10 개를 만든 다음 버튼을 클릭하면 저장할 이미지가 표시됩니다. 유일한 문제는 퀴즈를 시작할 때 이름을 입력해야하며 퀴즈를 통해 표시해야하며 결과 상자의 끝에 이름이 표시되고 "더 나아지기"와 같은 주석이 표시된다는 것입니다. 등등. 나는 그들의 이름을 이미지에 넣을 수 없거나 그렇지 않습니까?
Nathan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.