Html2canvas: Cara merender penuh bagian tersembunyi di div 'overflow:auto'

Dibuat pada 22 Feb 2012  ·  34Komentar  ·  Sumber: niklasvh/html2canvas

Saya memiliki div yang berisi semua elemen yang harus diubah menjadi gambar. Dan div itu diatur ke ' overflow:auto '. Saya ingin tahu bagaimana saya bisa mengekspor semua elemen (bahkan tersembunyi di pengguliran) ke gambar. Saya menghargai dan menyambut semua komentar dan jawaban Anda ...... Terima kasih sebelumnya ...

Komentar yang paling membantu

@ruthraprakash , saya memiliki masalah serupa. Ini berfungsi untuk tujuan sederhana saya pada versi terbaru:

function fullhtml2canvas(el) {
    return new Promise(resolve => {
        html2canvas(el, {
            width: el.scrollWidth,
            height: el.scrollHeight,
        }).then(canvas => {
            resolve(canvas);
        });
    });
}

Semua 34 komentar

Saat ini tidak ada opsi untuk merender halaman dengan opsi tertentu, jadi Anda harus memodifikasi halaman agar terlihat seperti yang Anda inginkan untuk dirender.

Dengan kata lain, jika Anda menghapus batas tinggi/lebar, menjalankan html2canvas, dan kemudian mengatur tinggi/lebar kembali ke nilai semula, Anda harus mencapai apa yang Anda cari.

Terima kasih banyak .... Saya akan mencoba apa yang Anda katakan ...

Saya mencoba untuk waktu yang lama ... Tapi itu membuat banyak masalah ... Saya tidak bisa mencapai apa yang Anda katakan. Saya menemukan bahwa itu berfungsi dengan baik ketika itu adalah 'tubuh' bahkan jika ada pengguliran ... Saya ingin mencapai hal yang sama untuk div yang memiliki elemen dengan pengguliran ... Jika Anda dapat membantu saya dengan masalah ini, itu akan menjadi sangat membantu bagi saya ... Saya menantikan komentar Anda ...

@niklasvh , saya mengalami masalah yang sama, dan satu-satunya solusi yang saya miliki adalah mengecilkan lebar elemen target sebelum panggilan ke html2canvas (tidak selalu merupakan opsi), atau menelepon html2canvas dua kali berturut-turut pada elemen yang sama. Berikut biola untuk menunjukkan masalah ini:

http://jsfiddle.net/fMeRC/1/ (contoh khusus ini hanya berfungsi untuk Chrome; Anda harus mengutak-atik lebar untuk melihat masalah di browser lain)

Ini pada dasarnya hanya terjadi ketika elemen lebih lebar dari jendela atau (document.width - 8) , saya tidak yakin mana yang lebih penting/relevansi langsung, dan ini dapat berubah di browser lain).

Mungkin terkait: #199 dan #108.

Mencoba childElement atau setel "overflow=visible" dan setelah disetel "overflow=auto|hidden|inherit" ?

childElement tanpa gaya, hanya untuk menerima konten div dengan overflow:

<div id="main"><!--// main div -->
<div class="mainContent"><!--// div without style (height: auto, width: auto, margin: 0, padding: 0) -->
...content...
html2canvas([$("#main div.mainContent").get(0)],...)

Terima kasih atas sarannya, @brcontainer. Saya telah mencoba pendekatan overflow: visible -> html2canvas( ... ) -> overflow: [old overflow] , meskipun flash dari konten tersembunyi/tersembunyi/tersembunyi-lagi terlalu terlihat (mungkin karena elemen target saya relatif kompleks). Meskipun saya baru saja menemukan varian solusi yang sedikit dioptimalkan yang tampaknya membuat perbedaan dalam hal itu:

html2canvas( targetElement, {
  onpreloaded: function(){ /* set parent overflow to visible */},
  onparsed: function(){  /* reset parent overflow */ },
  // ... onrendered, etc.
});

Ini menetapkan overflow menjadi 'terlihat' hanya untuk (apa yang saya pikirkan) jumlah waktu terpendek yang diperlukan untuk h2c untuk mengurai target dengan benar, sehingga menghilangkan flash hampir seluruhnya, setidaknya dalam kasus saya. Artinya, kita tidak lagi harus menunggu langkah rendering kanvas selesai sebelum mengatur ulang/menyembunyikan ulang overflow. Saya tidak tahu apakah pendekatan yang dimodifikasi ini akan bekerja untuk semua orang, tetapi saya pikir ini adalah solusi yang lebih baik daripada memanggil html2canvas( ... ) dua kali berturut-turut atau menambahkan barang tambahan ke DOM untuk membungkus konten target.

Bagaimanapun, ini masih merupakan bug nyata yang ingin saya lihat diperbaiki dengan benar. (Terutama karena tidak ada solusi yang tampaknya berfungsi dengan benar untuk saya di IE9&10, setidaknya - belum mencoba di IE11.)

_Catatan: Solusi yang disebutkan di atas tidak akan berfungsi dengan versi terbaru yang saat ini ada di master. Saya belum menguji, tetapi sepertinya Anda perlu menggunakan opsi oncloned sebagai gantinya, dan reset induk overflow sekarang akan dipanggil dalam panggilan balik Anda ke .then() . (Seharusnya juga memungkinkan untuk secara eksklusif membuat luapan induk terlihat di dalam dokumen kloning dan tidak khawatir tentang mengatur ulang apa pun.)_

Saya tidak mengerti mengapa menggunakan cara yang Anda lakukan, akan lebih baik seperti ini:

function SnapShotDOM(target,call){
    var data = {};

    //use jquery or getComputedStyle|style.overflow
    data.overflow = /*get overflow property*/;
    data.width = /*get width property*/;
    data.height = /*get height property*/;
    data.maxWidth = /*get maxWidth property*/;
    data.maxHeight = /*get maxHeight  property*/;

    target.style.overflow="visible !important";
    target.style.height="auto !important";
    target.style.maxHeight="auto !important";

    html2canvas(target, {
        "onrendered": function(canvas) {
            target.style.overflow = data.overflow;
            target.style.width = data.width;
            target.style.height = data.height;
            target.style.maxWidth = data.maxWidth;
            target.style.maxHeight = data.maxHeight;
            call(canvas);
        }
    });
}

SnapShotDOM(document.body,function(canvas){
    console.log(canvas);
});

atau gunakan kelas:

<style>
*.html2canvasreset{
    overflow: visible !important;
    width: auto !important;
    height: auto !important;
    max-height: auto !important;
}
</style>
<script>
function SnapShotDOM(target,call){
    var data = target.className;
    target.className += " html2canvasreset";//set className - Jquery: $(target).addClass("html2canvasreset");
    html2canvas(target, {
        "onrendered": function(canvas) {
            target.className = data;//old className - Jquery: $(target).removeClass("html2canvasreset");
            call(canvas);
        }
    });
}

SnapShotDOM(document.body,function(canvas){
    console.log(canvas);
});
</script>

Alasan saya tidak memasukkan apa pun yang terkait dengan overflow di onrendered adalah karena waktu antara parsing dan rendering dapat terlihat, dan menyetel ulang overflow sesegera mungkin (yaitu, tepat setelah parsing, sebelum rendering) lebih disukai untuk menghindari kilasan konten yang terlihat. Menempatkan reset overflow di onparsed malah menyelesaikan ini.

Saya mengacu pada "dimuat sebelumnya".

coba ini:

function SnapShotDOM(target,call){
    var data = target.className;
    target.className += " html2canvasreset";//set className - Jquery: $(target).addClass("html2canvasreset");
    html2canvas(target, {
        "onparsed": function() {
            target.className = data;//old className - Jquery: $(target).removeClass("html2canvasreset");
        },
        "onrendered": function(canvas) {
            call(canvas);
        }
    });
}

SnapShotDOM(document.body,function(canvas){
    console.log(canvas);
});

Penggunaan onpreloaded adalah untuk alasan yang sama--ini adalah pengoptimalan yang memungkinkan saya untuk memindahkan bagian un-hide overflow ke momen terbaru yang memungkinkan, tepat sebelum langkah penguraian, sehingga meminimalkan jumlah waktu yang konten benar-benar terlihat di layar. Anda dapat melihat cara kerjanya dalam kode di sini dan di sini .

@niklasvh , apakah masalah ini terkait dengan TODO yang ditemukan di sini ( options.useOverflow )?

versi apa yang kalian gunakan?.. saya dapat menemukan metode onparsed dan onpreloaded di versi saya..
saya menggunakan html2canvas-0.5.0-alpha1

@ejlocop Masalah ini diajukan tahun lalu untuk versi sebelumnya dan mungkin tidak relevan untuk kasus penggunaan Anda (#511).

Mereka memecahkan masalah? solusi paraa Saya mencari sesuatu dengan bagan Gantt saya, saya membutuhkan Anda sepenuhnya ...
overflow

ini tidak bekerja.

http://jsfiddle.net/fMeRC/368/

@pkpatels Mengapa tidak bekerja? Saya menjalankan biola Anda dan kalimat itu diberikan tanpa terputus ...
Saya juga mengalami masalah ini dan solusi yang berhasil untuk saya adalah yang disarankan di: #117

@uriklar Ini berfungsi untuk gulir horizontal bukan untuk vertikal. Lihat div saya. Ada tiga elemen berbeda di sana.

@uriklar solusi yang Anda sarankan juga tidak berfungsi ketika saya menggulir ke bawah div dan mengklik benar-benar terlihat.
screen shot 2016-03-16 at 1 41 09 pm

Bagaimana dengan mengatur ketinggian #text div ke auto sebelum merender dan mengatur ulang setelahnya? Itu akan bekerja.

Saya masih mengalami masalah dengan overflow di rilis terbaru (0,5.0-beta4). Saya mengambil solusi @usmonster dan menyesuaikannya dengan perubahan terbaru pada h2c dan Promises (seperti yang dijelaskan dalam catatan @usmonster ):

Catatan: Solusi yang disebutkan di atas tidak akan berfungsi dengan versi terbaru yang saat ini ada di master. Saya belum menguji, tetapi sepertinya Anda perlu menggunakan opsi oncloned sebagai gantinya, dan reset induk overflow sekarang akan dipanggil dalam panggilan balik Anda ke .then(). (Seharusnya juga memungkinkan untuk secara eksklusif membuat luapan induk terlihat di dalam dokumen kloning dan tidak khawatir tentang mengatur ulang apa pun.)

Jadi tanpa mengubah DOM sebenarnya dari halaman web Anda, Anda dapat mengubah dokumen kloning yang digunakan untuk rendering oleh h2c menggunakan callback onclone . Sebenarnya cukup sederhana, inilah panggilan h2c saya:

var renderingPromise = html2canvas($(item), {
    width: item.clientWidth,
    height: item.clientHeight,
    onclone: function(clone) {
            $(clone).find('.grid-stack-item-content')
                .css('overflow-x', 'auto')
                .css('overflow-y', 'auto');
        return true;
    }
}).then(
    function(c) {/* success */},
    function() {/* fail */}
);

Satu-satunya hal yang berhasil bagi saya adalah meletakkan kanvas di iframe, memanggil html2canvas di dalamnya, memanggil toDataURL() di kanvas, dan kemudian meneruskan gambar itu kembali ke jendela atas menggunakan panggilan balik. Saya kira Anda juga bisa mengembalikan objek kanvas.

return renderDocument(node.ownerDocument, options, node.ownerDocument.defaultView.innerWidth, node.ownerDocument.defaultView.innerHeight, index).then(function(canvas) { if (typeof(options.onrendered) === "function") { log("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas"); options.onrendered(canvas); } return canvas; });
mengubah
var width = options.width != null ? options.width : node.ownerDocument.defaultView.innerWidth; var height = options.height != null ? options.height+node.ownerDocument.defaultView.innerHeight : node.ownerDocument.defaultView.innerHeight; return renderDocument(node.ownerDocument, options, width, height, index).then(function (canvas) { if (typeof(options.onrendered) === "function") { log("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas"); options.onrendered(canvas); } return canvas; });

Ini dapat menjawab pertanyaan tentang luapan layar (lebar dan tinggi)

xzw123 memiliki solusi yang buruk: menyetel ownerDocument.defaultView.innerHeight secara manual menyebabkannya terlepas dari peristiwa ukuran jendela yang sebenarnya. Saya pikir akan lebih baik untuk melakukan ini dalam iframe. Saya tertarik untuk mencoba solusi Jordan.

Jordan, bagaimana Anda akhirnya menggunakan kanvas di iframe? Saya sedang mencobanya sekarang. Saya pikir ini harus menjadi solusi terakhir di html2canvas... komunikasi iframe harus dibuat tidak terlihat di luar API.

Ah ya, melakukannya dalam iframe dengan window.postMessage(myData, ... ) . Anda dapat memposting kembali seluruh url data dari piksel yang dirender. Saya baru saja memasukkan kode rendering saya ke HTML iframe, meneruskan data yang diperlukan untuk merender sumber HTML, membuatnya dirender ke kanvas, lalu mengeluarkan data toDataUrl kembali.

+1

Hai. Setelah mencari solusi dan mengamati bagaimana kode berjalan, saya menulis solusi rumit saya sendiri.

https://Gist.github.com/simonmysun/c6da13ce2827a374e71ccf07d9f08e2d

Ini bekerja untuk saya dan saya harap ini akan membantu seseorang yang membutuhkan.

Namun, saya tetap berharap dapat didukung di perpustakaan ini di masa depan.

saya masih belum mengerti, tetapi untuk masalah saya adalah gambar terpotong. saat menggunakan chrome Versi 54.0.2840.99 m
(setengah gambar mendapat tangkapan layar, tetapi setengah lainnya mendapat layar hitam)

// the timeline show up 100%, but cut off, cause its static and not dynamic.
// (its cut off from the screen,but the size, and picture show as normal, 100% show)
// after moving to the canvas, everthing that not in the screen will get blank in chrome  
// it depends to the user screen, if i zoom out my chrome, i get 100% image.

tetapi saat menggunakan Mozilla 50.0.2, berfungsi dengan baik tanpa zoom out. (100% gambar),

saya tidak tahu mengapa.

kode:

var zenleft = $("#leftPanel").width();  //calculate left side
var zenright = $(".dataPanel").width();  //calculate right side
var after = zenright + zenleft + 250;  // add all

//add the css, even after add overflow still not working
$("#timelineTarget").css({"background-color":"white","width":after});   

 html2canvas(canvTimeline, {
    onrendered: function (canvas) {
            $("#previewImage").html(canvas);
            getCanvas = canvas;
   }
});

image

Akhirnya saya memecahkan masalah ini dengan menambahkan

$("body").css({"width": "+="+after}); //after is a total of the width of the element i want to view

jadi

var zenleft = $("#leftPanel").width();  //calculate left side
var zenright = $(".dataPanel").width();  //calculate right side
var after = zenright + zenleft + 250;  // add all
$("body").css({"width": "+="+after});  //add the body

//add the css
$("#timelineTarget").css({"background-color":"white","width":after});   

 html2canvas(canvTimeline, {
    onrendered: function (canvas) {
            $("#previewImage").html(canvas);
            $("#timelineTarget").css({"background-color":"white","width":old});   //turn it back
            $("body").css({"width": "-="+after});   //turn it back
            getCanvas = canvas;
   }
});

berharap itu memecahkan masalah Anda sendiri.

onclone mungkin metode yang benar. Anda dapat mengubah css untuk mendapatkan apa yang Anda inginkan ....

Hai Semua, saya memiliki div yang dapat digulir. Ketika saya mengirim input div sebagai parameter kanvas, itu hanya menampilkan apa yang tersedia di viewport. Saya telah melalui semua solusi. saya tidak mengerti. Adakah yang bisa memberi tahu cara mengambil seluruh konten dalam div sebagai tangkapan layar.

@ruthraprakash , saya memiliki masalah serupa. Ini berfungsi untuk tujuan sederhana saya pada versi terbaru:

function fullhtml2canvas(el) {
    return new Promise(resolve => {
        html2canvas(el, {
            width: el.scrollWidth,
            height: el.scrollHeight,
        }).then(canvas => {
            resolve(canvas);
        });
    });
}

Saya memiliki masalah dengan mengambil tangkapan layar dari bagan garis waktu. Saya tidak mendapatkan nilai sumbu x. itu hanya membuat gambar bagan timline.
` demoFromHTML(e) {
e.preventDefault();

  let input = window.document.getElementById('divToPDF');


  html2canvas(input)
  .then((canvas) => {

    const imgData = canvas.toDataURL('image/jpeg');

    const pdf = new pdfConverter("l", "pt");
    pdf.addImage(imgData, 'JPEG', 15, 110, 800, 250);
    pdf.save('test.pdf');
  });


}

`

Saya mencoba untuk waktu yang lama ... Tapi itu membuat banyak masalah ... Saya tidak bisa mencapai apa yang Anda katakan. Saya menemukan bahwa itu berfungsi dengan baik ketika itu adalah 'tubuh' bahkan jika ada pengguliran ... Saya ingin mencapai hal yang sama untuk div yang memiliki elemen dengan pengguliran ... Jika Anda dapat membantu saya dengan masalah ini, itu akan menjadi sangat membantu bagi saya ... Saya menantikan komentar Anda ...

Tolong bisakah Anda menunjukkan kepada saya bagaimana Anda membuat tubuh bekerja?

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

tjchambers32 picture tjchambers32  ·  3Komentar

tibewww picture tibewww  ·  4Komentar

kunal886496 picture kunal886496  ·  3Komentar

diego-rey picture diego-rey  ·  3Komentar

ABHIKSINGHH picture ABHIKSINGHH  ·  3Komentar