Html2canvas: Как отрисовать скрытую часть в div 'overflow: auto'

Созданный на 22 февр. 2012  ·  34Комментарии  ·  Источник: niklasvh/html2canvas

У меня есть div, содержащий все элементы, которые нужно преобразовать в изображение. И для этого div установлено значение « overflow: auto ». Я хочу знать, как я могу экспортировать все элементы (даже скрытые при прокрутке) в изображение. Я ценю и приветствую все ваши комментарии и ответы ...... Заранее спасибо ...

Самый полезный комментарий

@ruthraprakash , у меня была аналогичная проблема. Это работает для моих простых целей в последней версии:

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

Все 34 Комментарий

В настоящее время нет возможности визуализировать страницу с определенными параметрами, поэтому вам необходимо изменить страницу, чтобы она выглядела так, как вы хотите.

Другими словами, если вы удалите ограничение высоты / ширины, запустите html2canvas, а затем установите высоту / ширину обратно на прежнее значение, вы должны достичь того, что ищете.

Большое спасибо .... Я попробую то, что вы сказали ...

Я долго пытался ... Но это создает массу проблем ... Я не мог добиться того, что вы сказали. Я обнаружил, что он хорошо работает, когда это «тело», даже если есть прокрутка ... Я хочу добиться того же для div, у которого есть элементы с прокруткой ... Если бы вы могли помочь мне с этой проблемой, это было бы очень помогли мне ... Я с нетерпением жду ваших комментариев ...

@niklasvh , у меня такая же проблема, и я могу только уменьшить ширину целевого элемента перед вызовом html2canvas (не всегда вариант) или вызвать html2canvas дважды подряд для одного и того же элемента. Вот скрипка, чтобы продемонстрировать проблему:

http://jsfiddle.net/fMeRC/1/ (этот конкретный пример работает только для Chrome; вам нужно поиграть с шириной, чтобы увидеть проблему в других браузерах)

Это в основном происходит только тогда, когда элемент шире окна или (document.width - 8) , я не уверен, что имеет более важное / прямое отношение, и это может измениться в других браузерах).

Вероятно, родственные: №199 и №108.

Пробовали childElement или установить «overflow = visible», а после установить «overflow = auto | hidden | inherit»?

childElement без стиля, только чтобы получить содержимое div с переполнением:

<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)],...)

Спасибо за предложения, @brcontainer. Я пробовал подход overflow: visible -> html2canvas( ... ) -> overflow: [old overflow] , хотя вспышка скрытого / не скрытого / скрытого контента была слишком заметной (возможно, потому, что мой целевой элемент относительно сложно). Хотя я только что придумал слегка оптимизированный вариант обходного пути, который, кажется, имеет значение в этом отношении:

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

Это устанавливает переполнение как «видимое» только в течение (как мне кажется) самого короткого времени, необходимого h2c для правильного анализа цели, таким образом почти полностью устраняя вспышку, по крайней мере, в моем случае. То есть нам больше не нужно ждать завершения этапа рендеринга холста перед сбросом / повторным скрытием переполнения. Я понятия не имею, подойдет ли этот модифицированный подход для всех, но я считаю, что это более приятный обходной путь, чем вызов html2canvas( ... ) дважды подряд или добавление дополнительных материалов в DOM для обертывания целевого контента.

В любом случае, это все еще реальная ошибка, которую я хотел бы исправить. (Тем более, что ни один обходной путь, похоже, не работает для меня правильно в IE9 и 10, по крайней мере - не пробовал в IE11.)

_Примечание: вышеупомянутый обходной путь не будет работать с новейшей версией, которая в настоящее время находится в мастерской. Я не тестировал, но похоже, что вам нужно будет вместо этого использовать параметр oncloned , и теперь в вашем обратном вызове будет вызываться сброс родительского переполнения на .then() . (Также должна быть возможность сделать видимым только родительское переполнение внутри клонированного документа и не беспокоиться о сбросе чего-либо вообще.) _

Не понимаю, зачем вы так использовали, лучше бы так:

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

или используйте класс:

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

Причина, по которой я не помещаю ничего, связанного с переполнением, в onrendered заключается в том, что время между синтаксическим анализом и рендерингом может быть заметным, и сброс переполнения как можно скорее (т.е. сразу после анализа, перед рендерингом) предпочтительнее чтобы избежать видимой вспышки содержимого. Помещение сброса переполнения в onparsed вместо этого выполняет это.

Я имел в виду "предварительную загрузку".

попробуй это:

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

Я использую onpreloaded по той же причине - это оптимизация, которая позволяет мне переместить скрытую часть переполнения в самый последний возможный момент, непосредственно перед этапом синтаксического анализа, тем самым минимизируя количество времени, в течение которого содержимое полностью видно на экране. Вы можете увидеть, как это работает, в коде здесь и здесь .

@niklasvh , эта проблема вообще связана с TODO, найденным здесь ( options.useOverflow )?

какую версию вы, ребята, использовали? .. Я могу найти методы onparsed и onpreloaded в моей версии ..
Я использую html2canvas-0.5.0-alpha1

@ejlocop Эта проблема была зарегистрирована много лет назад для предыдущей версии и может не иметь отношения к вашему варианту использования (№ 511).

Решили проблему? paraa solution Я ищу что-то с моей диаграммой Ганта, вы мне нужны полностью ...
overflow

это не работает.

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

@pkpatels Почему не работает? Я запустил вашу скрипку, и предложения были воспроизведены без обрезания ...
У меня также была эта проблема, и решение, которое сработало для меня, предложено в: # 117

@uriklar Он работает для горизонтальной прокрутки, а не для вертикальной. Оформить заказ на мой div. Здесь есть три разных элемента.

@uriklar решение, которое вы предлагаете, также не работает, когда я прокручиваю div вниз и нажимаю полностью видимый.
screen shot 2016-03-16 at 1 41 09 pm

Как насчет того, чтобы установить для высоты #text div значение auto перед рендерингом и сбросить его после? Это будет работать.

У меня все еще были проблемы с переполнением в самой последней версии (0.5.0-beta4). Я взял обходной путь примечании @usmonster ):

Примечание. Вышеупомянутый обходной путь не будет работать с новейшей версией, которая в настоящее время находится в мастерской. Я не тестировал, но похоже, что вам нужно будет вместо этого использовать опцию oncloned, и теперь в вашем обратном вызове для .then () будет вызываться сброс родительского переполнения. (Также должна быть возможность сделать исключительно видимым переполнение родителя внутри клонированного документа и вообще не беспокоиться о сбросе чего-либо.)

Таким образом, не изменяя фактический DOM вашей веб-страницы, вы можете изменить клонированный документ, используемый для рендеринга h2c, используя обратный вызов onclone . На самом деле это довольно просто, вот мой вызов h2c:

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

Единственное, что сработало для меня, - это поместить холст в iframe, вызвать внутри него html2canvas, вызвать toDataURL () на холсте, а затем передать это изображение обратно в верхнее окно с помощью обратного вызова. Я полагаю, вы также можете передать объект холста.

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; });
изменить на
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; });

Это может решить вопрос о переполнении экрана (как по ширине, так и по высоте).

У xzw123 плохое решение: установка ownerDocument.defaultView.innerHeight вручную заставляет его отвязаться от фактических событий изменения размера окна. Думаю, лучше всего это сделать в iframe. Я очень хочу попробовать решение Джордана.

Джордан, как вы в итоге использовали холст в iframe? Я пытаюсь это сделать сейчас. Я думаю, что это должно быть окончательное решение в html2canvas ... связь iframe должна быть невидимой вне API.

Ах да, выполнение этого в iframe с window.postMessage(myData, ... ) делает свое дело. Вы можете отправить обратно весь URL-адрес данных отрисованных пикселей. Я просто помещаю свой код рендеринга в HTML iframe, передаю данные, необходимые для рендеринга источника HTML, передаю его на холст, а затем возвращаю данные toDataUrl обратно.

+1

Привет. После поиска решений и наблюдения за тем, как работает код, я пишу собственное непростое решение.

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

Это работает для меня, и я надеюсь, что это поможет кому-то, кто в этом нуждается.

Тем не менее, я все еще надеюсь, что в будущем он будет поддерживаться в этой библиотеке.

Я до сих пор не понимаю, но моя проблема в том, что изображение обрезается. при использовании хром версии 54.0.2840,99 м
(половина изображения сделана скриншотом, но другая половина имеет черный экран)

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

но при использовании Mozilla 50.0.2 он работает нормально без уменьшения масштаба. (100% изображение),

я не знаю почему.

код:

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

Наконец, я решил эту проблему, добавив

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

так

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

надеюсь, что это решит вашу проблему.

onclone может быть правильным методом. Вы можете изменить css, чтобы получить то, что хотите ....

Привет всем, у меня есть div, который можно прокручивать. Когда я отправляю ввод div как параметр холста, он просто отображает то, что доступно во вьюпорте. Я перебрал все решения. Я не понял. Может ли кто-нибудь сказать, как взять весь контент в div как снимок экрана.

@ruthraprakash , у меня была аналогичная проблема. Это работает для моих простых целей в последней версии:

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

У меня не получается сделать снимок экрана с временной шкалой. Я не получаю значение оси x. это просто создание образа временной диаграммы.
`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');
  });


}

`

Я долго пытался ... Но это создает массу проблем ... Я не мог добиться того, что вы сказали. Я обнаружил, что он хорошо работает, когда это «тело», даже если есть прокрутка ... Я хочу добиться того же для div, у которого есть элементы с прокруткой ... Если бы вы могли помочь мне с этой проблемой, это было бы очень помогли мне ... Я с нетерпением жду ваших комментариев ...

Пожалуйста, покажи мне, как твое тело работает

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

AlphaDu picture AlphaDu  ·  4Комментарии

Josh10101010 picture Josh10101010  ·  3Комментарии

kunal886496 picture kunal886496  ·  3Комментарии

anthonymejia picture anthonymejia  ·  4Комментарии

deepender87 picture deepender87  ·  4Комментарии