JavaScript ile div'in ekran görüntüsünü nasıl alabilirim?


175

"HTML Quiz" adlı bir şey yapıyorum. Tamamen JavaScript ile çalıştı ve oldukça havalı.

Sonunda, "Sonuçlarınız:" yazan bir sonuç kutusu açılır ve ne kadar zaman aldıklarını, yüzde kaçını ve 10'dan kaç soru aldıklarını gösterir. "Yakalama sonuçları" ve bir şekilde bir ekran görüntüsü veya div bir şey almak ve sonra sadece sağ tıklayın ve "Görüntüyü farklı kaydet."

Sonuçlarını başkalarıyla paylaşabilmeleri için bunu gerçekten yapmak isterim. Sonuçları "kopyalamasını" istemiyorum çünkü bunu kolayca değiştirebiliyorlar. Eğer görüntüde söylediklerini değiştirirlerse, oh iyi.

Bunu yapmanın bir yolunu veya benzeri bir şey bilen var mı?


2
Phantomjs.org'a bir göz atın . Bunu kullanarak, sunucu tarafında HTML sayfasının tam görüntüsünü oluşturabilir ve kullanıcıya indirme bağlantısı verebilirsiniz.
Joshua

Güzel yazı görüntü HTML içeriği dönüştürmek ve indirmek codepedia.info/…
Satinder singh

Yanıtlar:


99

Hayır, bir öğeyi 'ekran görüntüsü' almanın bir yolunu bilmiyorum, ancak yapabileceğiniz şey, sınav sonuçlarını bir tuval öğesine çizmektir, daha sonra görüntünün içeriğiyle bir URI almak için HTMLCanvasElementnesnenin toDataURLişlevini kullanmaktır data:.

Sınav bittiğinde şunu yapın:

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

Kullanıcı "Yakala" yı tıkladığında şunu yapın:

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

Bu, kullanıcının ekran görüntüsünü kaydetmesini sağlayan 'ekran görüntüsü' ile yeni bir sekme veya pencere açar. Bir tür 'farklı kaydet' iletişim kutusunu çağırmanın bir yolu yoktur, bu yüzden bence yapabileceğiniz en iyi şey budur.


Teşekkürler!! Tuval hakkında hiçbir şey bilmiyorum, ama öğreneceğim. Canvas 2D çizim efektlerini nasıl kullanırım? Bana bu konuda yardımcı olabilir misiniz? Çok teşekkürler! :)
Nathan

5
Mozilla'nın belgelerini deneyin, takip etmek gerçekten çok kolay: developer.mozilla.org/en/canvas_tutorial
Delan Azabani

Yeni bir pencerede / sekmede açmak yerine, satır içi iletişim kutusunda açabilir miyim? (Fancybox ışık kutusu eklentisi gibi mi?)
Nathan

Evet, bir ile bir satır içi iletişim kutusu olabilir imgonun sahip olduğu srciçin set data:URI. Ancak, bu gerçekten gerekli değildir - canvaskendini satır içi iletişim kutusuna koyabilirsiniz ; kullanıcılar sağ tıklayıp geçerli durumu resim olarak kaydedebilir.
Delan Azabani

Teşekkürler :) Ben sağ tıklayın ve "resmi farklı kaydet" tıklayın böylece görüntü sürümünü kullanabilirsiniz
Nathan

90

Bu html2canvas ve FileSaver.js kullanan @ Dathan'ın cevabının bir uzantısıdır .

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


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

Bu kod bloğu, kimliğine sahip düğmenin btnSavetıklanmasını bekler . Bu olduğunda, widgetdiv'ı bir tuval öğesine dönüştürür ve sonra div'ı "Dashboard.png" adlı bir görüntü olarak kaydetmek için saveAs () FileSaver arabirimini (yerel olarak desteklemeyen tarayıcılarda FileSaver.js aracılığıyla) kullanır.

Bu çalışmanın bir örneği bu kemanda mevcuttur .


7
Referansları eklemem gerekiyordu: html2canvas, fileaver, blob, canvas-toBlob. Bundan sonra işe yaradı. Teşekkürler!
sirthomas

1
Harika, bu kabul edilen cevap olmalı. Kolay tak ve çalıştır.
16:35

Bunun three.js ile nasıl çalışacağını biliyor musunuz? Üç.js renderer / canvas (renderer.domElement) içinde bir div var ve bunun üzerine divs. Ana DIV'nin anlık görüntüsünü alıp her şeyi yakalamak ister miyim? Mümkün mü? Teşekkürler!
Rankinstudio

1
DOM'nizde görüntünün görünmesini engelleyebilir misiniz? Hemen indirmeye gidemez mi?
kulan

1
Bu ilk denemede benim için harika çalıştı ve hatta orijinal CSS stiline benziyor. İnanılmaz derecede doğru. Bu doğruluk seviyesiyle sanal bir ekran görüntüsü. Eklemek zorunda olduğum 2 kütüphane için CDN kullandım: <! - html2canvas -> <script src = " cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/… > <! - dosya koruyucu - > <script src = " cdn.jsdelivr.net/npm/file-saver@2.0.2/dist/… >
OG Sean

13

Saatler süren bir araştırmadan sonra, bir öğenin ekran görüntüsünü almak için bir çözüm buldum, origin-clean FLAG ayarlanmış (XSS'yi önlemek için) , bu yüzden örneğin Google Haritalar'ı (benim durumumda) bile yakalayabilirsiniz. Ekran görüntüsü almak için evrensel bir işlev yazdım. İhtiyacınız olan tek şey html2canvas kütüphanesidir ( https://html2canvas.hertzen.com/ ).

Misal:

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

Unutmayın console.log()ve alert()görüntünün boyutu büyük ise çıktı üretmek Yapmayacağım.

İşlev:

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 işlevini tanımladığınız yerde
Bharathi

GetScreenshotOfElement () işlevine ulaşılmadan önce html2canvas kütüphanesini (yazımdaki bağlantıya bakın) entegre ettim. Örneğin, <script> etiketiyle. Sadece html2canvas'ı indirin ve projenize kopyalayın.
orange01

@ orange01 - Google haritasının sokak şeritlerini hala yakalayamıyorum. Bu yalnızca yakınlaştırma ve uzaklaştırma düğmesi, Harita ve uydu metnini görüntüler. tam haritayı yakalamak için yardım lütfen. Teşekkürler
Farhan Sahibole

7

"Farklı kaydet" iletişim kutusuna sahip olmak istiyorsanız, resmi uygun başlıklar ekleyen php komut dosyasına geçirmeniz yeterlidir

Örnek "hepsi bir arada" komut dosyası 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

Ekran görüntüsü alamazsınız: bunu yapmanıza izin vermek sorumsuz bir güvenlik riski olacaktır. Ancak şunları yapabilirsiniz:

  • Sunucu tarafında bir şeyler yapın ve bir görüntü oluşturun
  • Tuval'e benzer bir şey çizin ve bunu bir görüntüye dönüştürün (onu destekleyen bir tarayıcıda)
  • Doğrudan görüntüye çizim yapmak için başka bir çizim kitaplığı kullanın (yavaş, ancak herhangi bir tarayıcıda çalışır)

Teşekkürler! Tuvalle gideceğim, çünkü herhangi bir "çizim kütüphanesi" ne de bunun nasıl yapılacağını bilmiyorum. Tuvalde o kadar da iyi değilim ama deneyeceğim.
Nathan

2
Üzgünüm ben bu google geliyor gibi yorum yapmak zorunda ama WTF "sorumsuz güvenlik riski" javascript verilen kabloları içinde bir ekran görüntüsü veya bir çekim almak ve BASE64 kodlanmış verileri bir dize olarak döndürmek izin verirseniz neden sorabilir miyim Güvenlik sorunu
Barkermn01

@MartinBarker Birinin Facebook sayfasını bir iframe'de çekip (sonra) ekran görüntüsünü alabilirim. Normalde bir siteler arası iframe, XSS'yi önlemek için erişilebilir DOM'nin bir parçası değildir, ancak bu durumda tarayıcı satıcısının bunu durdurması çok daha zor olacaktır.
bgw

2
@MartinBarker Javascript, kullanıcının farkına bile varmadan verileri kötü niyetli bir kaynağa verebilirken, "yazdırma ekranı" kullanıcı tarafından kontrol edilir ve bazı rastgele güvenilmeyen web siteleri tarafından kontrol edilmez.
bgw

2
Ne kadar dayak. @PiPeep, Bir web sayfası bir Facebook iFrame'i yükleyebilirse, zaten yalıtım var, neden bu yalıtımı bir ekran görüntüsü API'sı ile genişletmiyorsunuz? Örneğin. Div.ToPNG (), yukarıda bahsi geçen iFrame'in nereye atıldığını? Sorumsuz bir güvenlik riski değildir, sadece yerleşik değildir ve hiç kimse böyle bir yerleşik ekran görüntüsü API'sını geliştirirken "potansiyel" gizlilik / güvenlik sorunları ile çalışmamıştır. Örneğin, intranet web uygulamalarının desteklenmesi gibi sayısız kullanım senaryosu için son derece yararlı olacaktır.
Todd

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

Htmlshot'a bir göz atın paketine , ardından istemci tarafı bölümünü derinlemesine kontrol edin :

npm install htmlshot

Bu htmlshot projesi hala devam ediyor mu? Npm'den github bağlantısı hala var gibi görünmüyor. Bunun için başka bir web sitesi var mı?
whatsTheDiff

@whatsTheDiff:: bana ihtiyaçlarınızı verin ve bu kütüphanenin yazarı olduğumdan size yardımcı olacağımdan emin olun.
Abdennour TOUMI

2
Teşekkürler @ abdennour-toumi. Ben sadece kod bakmak için bir npm yükleme yaptım. Görünüşe göre html2canvas'ı denedim ve IE'de sorun yaşıyorum ve SVG'ler ve sayfamın karmaşıklığı nedeniyle. Görünüşe göre bu kütüphane bu konuda bana yardımcı olmayacak.
whatsTheDiff

4
Müşteriniz IE'den kaçınmalıdır .. onlara söyleyin!
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>

alıntı


1

Bu kodu, html2canvas'ta div kimliğini tanımlamanız gereken belirli bir alanın ekran görüntüsünü yakalamak için kullanabilirsiniz. Ben burada kullanıyorum 2 div-:

div id = "araba"
div id = "chartContainer"
Eğer sadece araba yakalamak istiyorsanız o zaman araba kullanın Ben burada araba yakalama sadece sen grafik değiştirmek için grafikContainer değiştirebilirsiniz html2canvas ($ ( '#car') bu kodu kopyalayıp yapıştırın

<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
Neden jQuery iki kez dahil edilir ve neden jQuery UI dahil edilir? Dürüst olmak gerekirse, burada söyleyebileceğimden jQuery'ye ihtiyaç yoktur. document.getElementById('car')veyadocument.querySelector('#car')
Nathan

aslında projem üzerinde çalışıyorum. bu yüzden sadece kütüphaneyi kaldırmayı unutuyorum ve hiçbir şey.
Rudra Pratap Singh

0

Bildiğim kadarıyla bunu yapamazsın, yanılmış olabilirim. Ancak ben php ile bunu yapmak, php standart fonksiyonları kullanarak bir JPEG oluşturmak ve daha sonra görüntüyü göstermek, çok zor bir iş olmamalı, ancak DIV içeriği ne kadar gösterişli bağlıdır


OP, sunucu tarafı işlemeyi kullandığını asla önermedi, ancak eğer olsaydı, bu iyi olurdu.
Delan Azabani

Evet, ne yazık ki sunucu tarafındaki şeyleri kullanamıyorum. Muhtemelen yukarıdaki cevaplardan biriyle gideceğim. Ama teşekkürler! :)
Nathan

-3

Bildiğim kadarıyla javascript ile mümkün değil.

Her sonuç için yapabilecekleriniz bir ekran görüntüsü oluşturun, bir yere kaydedin ve sonucu kaydet'i tıkladığınızda kullanıcıyı işaret edin. (Sonuçların hiçbiri sadece 10 değil, bu yüzden sonuçların 10 jpeg görüntüsünü oluşturmak için büyük bir anlaşma değil)


Cevapladığınız için teşekkürler :) Haklısınız! Sonuçların sadece 10 JPG görüntüsünü oluşturabilirim ve sonra düğmeyi tıkladıklarında, kaydedilecekleri görüntüyü gösterir. Tek sorun, sınavı başlattıklarında, adlarını girmek zorunda oldukları ve sınavı görüntüleyeceğim ve sonuç kutusunun sonunda, adlarını gösterdiği ve "Daha İyi Olmak" gibi bir yorum söylediği vb. Onların ismini resme koyamaz mıydım yoksa?
Nathan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.