Экспорт карты Leaflet со слоями геоджонов в png в Angular 5 - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть листовка с большим количеством геойсонов. Я хочу иметь возможность экспортировать изображение карты в формате PNG. Я попробовал плагин leaflet-image, который экспортирует базовую карту, и я также попытался (независимо) из библиотеки html2canvas вывести содержимое div карты в файл png.

К сожалению, при выводе с использованием leaflet-image отображается только фоновый слой (карта), а не какая-либо из областей геоджонов, тогда как при выводе результатов с использованием html2canvas отображаются слои, но не фоновая карта.

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

html2canvas гораздо более перспективный. Используя это и файл-заставку, я смог вывести полное изображение и регионы следующим образом:

html2canvas(myMap, {
            allowTaint:false,
            useCORS: true,
            width: 650,
            height: 500,

        }).then(canvas => {
            canvas.toBlob((blob) => {
                saveAs(blob, "my-map.png");
            });
        });

Это сработало блестяще, за исключением одной проблемы - области рендеринга на холсте обрезаны в неправильном положении. То есть смещение региона неверно. Вот пример. Нижняя и правая части карты должны быть покрыты краем цветными участками хороплета: leaflet image with regions, clipped

Как заставить регионы правильно отображаться на карте, а не обрезаться в неправильном месте?

Редактировать: Я посмотрел на проблему на сайте html2canvas здесь , которая выглядела многообещающе. У меня, похоже, нет проблемы трансформации как таковой, но был кто-то, кто испытал, как мне казалось, проблему смещения слоя. Я реализовал их решение здесь:

function redraw() {
    var lat_tmp = map.getCenter().lat;
    var lng_tmp = map.getCenter().lng;
    map.setView([-66.22149259832975, -1.142578125]);
    setTimeout(function () {
        waitForTilesToLoad()
    }, 50000);
    map.setView([lat_tmp, lng_tmp]);
}

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

Ответы [ 5 ]

0 голосов
/ 29 мая 2019

С момента написания этого вопроса прошло немало времени. Решение, которое в конечном итоге сработало для меня, состояло в том, чтобы купить Telerik Reporting и внедрить любое картографическое решение, в котором я нуждался. Это очень хороший вариант, и он всегда работал для меня, поэтому, если у вас есть такая возможность, я очень рекомендую его. Вы также получаете несколько различных форматов файлов из коробки, и решение выглядит значительно более профессиональным. Просто вариант для рассмотрения.

0 голосов
/ 07 февраля 2019

Попробуйте удалить отступы de renderer с вашей карты, а затем экспортируйте. У меня это сработало.

В вашем случае что-то подобное

myMap.getRenderer(myMap).options.padding = 0;
html2canvas(...
0 голосов
/ 02 мая 2018

Я проделал большую работу по смещению геоджона, чтобы объединить область просмотра с фоновыми плитками, из ссылки html2canvas выше. Я получил правильную карту, если переместил карту, но не при увеличении. Это очень сложно, и я бы предпочел этого не делать, если смогу избежать этого. Вероятно, это худший способ сделать это: если листовка изменится, решение сломается.

dom-to-image дает мне все, что мне нужно для создания изображения из dom. Leaflet Easy Print не дает мне ничего лишнего по сравнению с тем, что дает мне dom-to-image. Есть ошибки в консоли с dom-to-image, и такие же ошибки появляются при использовании листовки easy print. Я также хочу сам контролировать экспорт изображений. Недостатком dom-to-image является то, что он работает только в Chrome и Firefox. Нет IE, нет Edge, нет Safari. Поэтому я опубликовал это как возможное решение для людей, которым не нужно беспокоиться об этих ограничениях, и надеюсь, что позже мы найдем лучшее решение.

dom-to-image - отличная находка, потому что я могу использовать его и с другими объектами, такими как диаграммы. Престижность Потемкину за помощь в отправке меня по этому пути.

Вот решение с использованием domtoimage и файловой заставки:

import { saveAs } from "file-saver";
import domtoimage from "dom-to-image";

domtoimage.toPng(myMapDomObject).then((myImage: string) => {
            const commaPos = myImage.indexOf(",");
            if (commaPos > 0) myImage = myImage.substring(commaPos + 1);
            const byteArray = Util.encodeByteArray(myImage);
            const blob = new Blob([byteArray], { type: "image/png" });
            saveAs(blob, "mymap.png");
        });

Метод Util.encodeByteArray - это мой собственный метод преобразования строки изображения в байтовый массив для создания большого двоичного объекта, который можно использовать для экспорта. Это имеет проблемы, если изображения становятся огромными, по-видимому, хотя это никогда не случалось со мной. Вероятно, есть лучший способ сделать это, о котором я сейчас не знаю.

export class Util {
    static encodeByteArray(bytes: string) {
        const byteCharacters = atob(bytes);
        const byteNumbers = new Array(byteCharacters.length);
        for (let i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i);
        }
        const byteArray = new Uint8Array(byteNumbers);
        return byteArray;
    }
}

Кроме того, я исследую, как работает leaflet.browser.print. Кажется, что он может дать тот же результат и является кросс-браузерным, но обеспечивает только печать. Исследование его кода на GitHub может предоставить более кросс-браузерное решение, если я смогу решить, как экспортировать внутреннее изображение.

0 голосов
/ 10 января 2019

тон говорит:

Нижняя и правая части карты должны быть покрыты краем цветными участками хороплета:

Я нашел простое решение этой проблемы!

  1. Установить значение заполнения рендерера (https://leafletjs.com/reference-1.4.0.html#renderer-padding) = 0
  2. Установить значение "windowWidth" (http://html2canvas.hertzen.com/configuration) = document.documentElement.clientWidth.

Надеюсь, это поможет вам! Удачи.

0 голосов
/ 30 апреля 2018

Недавно у меня возникла та же проблема, и я обращался к той же цитируемой теме, пытаясь управлять html2canvas.

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

Наконец, я попробовал несколько других плагинов, и нашел этот вполне удовлетворительным:

Листовка Easy Print

Без сбоев, чистый экспорт в png.

...