html2canvas захватывает все, кроме содержимого внутреннего холста

#javascript #leaflet #webgl #html2canvas

#javascript #листовка #webgl #html2canvas

Вопрос:

У меня есть карта, отображаемая с помощью leaflet .

Мне нужно сделать снимок экрана этой карты с помощью html2canvas .

Чтобы использовать html2canvas , мне нужно предоставить элемент DOM для capture ( elementToCapture ) и необязательную конфигурацию ( html2canvasConfiguration ) .

 var html2canvasConfiguration = {
    useCORS: true,
    width: map._size.x,
    height: map._size.y,
    backgroundColor: null,
    logging: true,
    imageTimeout: 0
};

var elementToCapture = map._container.getElementsByClassName('leaflet-pane leaflet-map-pane')[0];
html2canvas(elementToCapture, html2canvasConfiguration).then(function (canvas) {
    var link = document.createElement('a');
    link.download = 'test.png';
    link.href = canvas.toDataURL();
    link.click();
    link.remove();
})
 

Я извлекаю элемент по leaflet-pane leaflet-map-pane классу, который в основном представляет всю карту, включая элементы управления (кнопки увеличения / уменьшения масштаба, масштабирование и т. Д.), Пользовательские маркеры, всплывающие подсказки, наложения, всплывающие окна.

Весь DOM выглядит так

 <div class="leaflet-pane leaflet-map-pane">
    <div class="leaflet-pane leaflet-tile-pane">
        <div class="leaflet-gl-layer mapboxgl-map">
            <div class="mapboxgl-canvas-container">
                <canvas class="mapboxgl-canvas leaflet-image-layer leaflet-zoom-animated"></canvas>
            </div>
            <div class="mapboxgl-control-container"></div>
        </div>
    </div>
    <div class="leaflet-pane leaflet-shadow-pane"></div>
    <div class="leaflet-pane leaflet-overlay-pane"></div>
    <div class="leaflet-pane leaflet-marker-pane"></div>
    <div class="leaflet-pane leaflet-tooltip-pane"></div>
    <div class="leaflet-pane leaflet-popup-pane"></div>
<div class="leaflet-control-container"></div>
 

Проблема, с которой я столкнулся, заключается leaflet-pane leaflet-tile-pane в том, что элемент (в частности, содержимое внутреннего canvas ) не захватывается html2canvas . Проще говоря, я вижу все на карте, но я не вижу саму карту.

введите описание изображения здесь

введите описание изображения здесь

ОБНОВЛЕНИЕ 1:

Версия, которую я использую в настоящее время, является 1.0.0-rc.1 (последней).

ОБНОВЛЕНИЕ 2:

Природа холста такова webgl . Может ли это быть проблемой? В соответствии с этим они поддерживают webgl холсты.

ОБНОВЛЕНИЕ 3:

Я попытался получить холст программно и вызвать toDataURL его. Это привело к пустому скриншоту, даже при preserveDrawingBuffer взломе.

ОБНОВЛЕНИЕ 4:

Как ни странно, он захватывает не только определенные холсты. Я создал 2d холст (путем добавления preferCanvas в конфигурацию карты), и он был показан.

Комментарии:

1. github.com/niklasvh/html2canvas/issues/1311 Может ли это быть как-то связано? Они добавили возможность removeContainer: false временно исправить это.

2. Проблема должна быть исправлена в последней версии от 4/10/2019: github.com/niklasvh/html2canvas/releases/tag/v1.0.0-rc.1

3. @TheBlackIPs Спасибо. Я только что попробовал, и это ничего не изменило. Я использую последнюю версию.

4. Когда вы вызываете html2canvas? Вы уверены, что у страницы было время для рендеринга? Есть ли какой-либо способ, которым вы могли бы предоставить пример в виде фрагмента?

5. @TheBlackIPs да, я уверен. Код выполняется при нажатии кнопки. Кнопка отображается на слое управления картой.

Ответ №1:

Попробуйте это, добавьте это в начало своей страницы перед любыми другими сценариями

 <script>
HTMLCanvasElement.prototype.getContext = function(origFn) {
  return function(type, attribs) {
    attribs = attribs || {};
    attribs.preserveDrawingBuffer = true;
    return origFn.call(this, type, attribs);
  };
}(HTMLCanvasElement.prototype.getContext);
</script>
 

Помогает ли это?

Комментарии:

1. Я хочу поцеловать тебя 🙂 Не могли бы вы подробнее рассказать о том, почему это работает? Принудительно ли он html2canvas устанавливается preserveDrawingBuffer каждый раз, когда извлекает контекст холста?

2. Вы не можете установить атрибуты canvas после получения контекста. Они могут быть установлены только один раз во время создания

3. должно ли это быть встроено или есть какое-либо более приятное / чистое решение?

4. Вы можете поместить это в сценарий и включить его.

5. Хороший! Я был в тупике