Заснемане на екранни снимки на DOM Elements: Server Side VS. Подходи от страна на клиента

Преди няколко седмици писах за Chatilyzer - нов страничен проект, над който работя през изминалия месец.

Бърз преглед на приложението и потока на приложението: Chatilyzer ви позволява да получавате статистически данни за вашите WhatsApp чатове. За да работи приложението, трябва да качите експортиран * .txt файл на чат WhatsApp. Chatilyzer анализира и анализира текста и извлича някои интересни данни от него. След това ще бъдете пренасочени към страница с резултати, където виждате приятна визуализация на активността на вашия чат.

Пример за страница с резултати от Chatilyzer

Едно от предизвикателствата, които имах при разработването на това уеб приложение, беше да позволя на потребителите да създадат екранна снимка на страницата с резултати и да я изтеглят, за да могат да я споделят в своята група - вместо да споделят URL адрес на страницата.

Подход от страна на сървъра (NodeJS)

Започнах с подхода от страна на сървъра, използвайки PhantomJS и NPM модул, наречен „Node Webshot“. Той има много прост api, който ви позволява да създавате екранни снимки от даден URL адрес:

импортиране на уебсайт от „webshot“;

webshot ('https://chatilyzer.com', 'chat.png', функция (грешка) {
  // екранната снимка сега е запазена в chat.png
});

След като създадох екрана, трябваше да го кача в облачно хранилище и да изпратя обратно URL адреса на изображението на страната на клиента, за да мога да позволя на потребителя да изтегли изображението.

Професионалисти:

  • Готов за употреба модул.
  • Снимката на екрана се запазва в облака, така че да е достъпна по всяко време.
  • Гъвкав api, който ви позволява да зададете желаната ширина и височина на екрана.

Недостатъци:

  • Всичко или нищо - екранната снимка заснема цялата страница и не можете да контролирате конкретен елемент, който искате да заснемете.
  • Визуализация - Ако трябва да изчакате да се зареди асинхронният JS, преди да заснемете екрана, може да изпаднете в проблеми.
  • Околна среда - Като се има предвид, че не сте в реална среда на браузър, PhantomJS не обработва персонализирани / Google шрифтове като правилни, което води до шрифт по подразбиране, който се изобразява във вашия екран.
  • Съхранение - След създаването на екрана трябва да го запишете в облачно хранилище, за да върнете валиден URL адрес на изображението на потребителя. Това означава, че имате нужда от доставчик на облачно хранилище, което потенциално може да ви струва повече пари.
  • Сигурност - Ако данните на екрана са чувствителни, запазването на копие в облака не е добър подход.

EDIT: След като получите някои отзиви от общността, се оказва, че има още едно сървърно решение, използващо NPM модул, наречен „Puppeteer“, който работи върху Chrome без глава. Ето как да създадете екранна снимка с Puppeteer:

const puppeteer = изисквам ('puppeteer');

(async () => {
  const браузър = изчакайте puppeteer.launch ();
  страница const = изчакайте browser.newPage ();
  изчакайте page.goto („https://chatilyzer.com“);
  изчакайте page.screenshot ({path: 'chatilyzer.png'});

  изчакайте browser.close ();
}) ();

Този модул би решил всички или нищо, проблемите с визуализацията и околната среда, тъй като осигурява същия двигател на визуализация като Chrome.

Подход от страна на клиента

Не намерих резултата от страна на сървъра достатъчно добър за моя случай, така че започнах да проучвам други опции.

Открих изключително готина JS библиотека, наречена „html2canvas“, която както подсказва името, ще превърне HTML елемент в елемент на платното.

уебсайт html2canvas

Както можете да видите, той също е много лесен за използване. По принцип викате метода html2canvas и предавате DOM елемент като аргумент. Този метод връща обещание, което можете да използвате за извличане на елемент на платно.

html2canvas (document.querySelector ("# улавяне")). тогава (canvasElm => {
    document.body.appendChild (canvasElm);
});

След това искате да активирате вашия потребител да изтегли екрана.

Начинът да го направите е с помощта на метода JS toDataURL, както може да видите по-долу:

// Вземете base64 низ за данни
var imageType = 'изображение / png';
var imageData = canvasElm.toDataURL (imageType);
// Отворете низ от данни в текущия прозорец
document.location.href = imageData.replace (imageType, 'image / octet-stream');

Има друга JS библиотека, наречена „canvas2image“. Препоръчвам да го използвате по-скоро да го напишете сами, тъй като осигурява по-голяма гъвкавост и също така ви позволява да генерирате етикет за изображение от елемента на платното. Така че можете да получите същия резултат, като използвате:

Canvas2Image.saveAsPNG (canvasElm, ширина, височина);

Професионалисти:

  • WYSIWYG - Резултатът е 1: 1 от това, което виждате на екрана.
  • Без страна на сървъра - Всички работят в браузъра.
  • Сигурност - Ако данните на екрана са чувствителни, заснемането им от страна на клиента е много по-сигурно, тъй като сървърът не е запознат с резултатите и не записва копие на друго място.

Недостатъци:

  • Съвместимост - html2canvas не се поддържа във всички браузъри
  • Скъпо - Въпреки че html2canvas връща обещание, това все още е скъпо действие, а за големите и сложни компоненти може да отнеме няколко секунди, преди да получите резултати.
  • Тесен изглед - Ако използвате тесен екран (например в мобилен телефон), екранният екран ще бъде тесен, както и заснема екрана от реалния изглед (това може да се реши, като се предаде фиксирана ширина като аргумент на canvas2html или като отворите рамка с желаната ширина във фонов режим, заснемете екрана и изпратете обратно изображенията с postMessage).
  • Поддръжка на елементи - Не всички html елементи се поддържат в html2canvas. Например, други елементи на платното, рамки и светкавица изобщо няма да бъдат изобразявани.

В заключение

Има два подхода как да заснемете екранна снимка от html елементи и трябва да помислите какво отговаря на нуждите на вашето приложение.

Подходът от страна на сървъра е този, който избирате, когато имате нужда от крос браузър / платформа, и не сте сигурни, че вашите потребители ще имат правилния браузър, за да заснемат екранна снимка. Цената, която ще трябва да платите, е както физическо плащане за услугата за съхранение в облак, така и неточни резултати.

Подходът от страна на клиента е добър, когато сте сигурни, че вашите потребители ще имат браузър, който може да заснема екрана (или сте готови да платите цената за тези, които не са) и когато точността е задължителна за екрана.

Бърза мисъл - предполагам, че най-добрият подход ще бъде комбинирането между тях. Можете да проверите дали съвместимостта на браузъра на потребителя има необходимата ви поддръжка, за да заснемете екранна снимка, и ако не, връщане към подхода от страна на сървъра.

Надявам се, че ви е харесала статията. Плескайте, че ви хареса :)

Знаете ли за други начини за създаване на екранни снимки на уеб страници с NodeJS? Споделете в коментари!