Захоп скрыншотаў элементаў DOM: Side Server VS. Кліентскі падыход

Некалькі тыдняў таму я пісаў пра Chatilyzer - новы пабочны праект, над якім я працаваў у мінулым месяцы.

Кароткі агляд прыкладання і патоку прыкладання: Chatilyzer дазваляе атрымаць статыстыку аб чатах WhatsApp. Для таго, каб прыкладанне працавала, вам трэба загрузіць экспартаваны * .txt файл чата WhatsApp. Chatilyzer разбірае і аналізуе тэкст і здабывае з яго цікавыя дадзеныя. Затым вы будзеце перанакіраваны на старонку вынікаў, дзе вы бачыце прыемную візуалізацыю актыўнасці вашага чата.

Прыклад старонкі вынікаў Chatilyzer

Адной з праблем, якія ўзнікалі пры распрацоўцы гэтага вэб-прыкладання, было дазволіць карыстальнікам ствараць скрыншоты старонкі вынікаў і загружаць яе, каб яны маглі падзяліцца ім у сваёй групе, а не падзяляць URL на старонку.

Падыход на баку сервера (NodeJS)

Я пачаў з падыходу да сервера, выкарыстоўваючы PhantomJS і модуль NPM пад назвай "Node Webshot". Ён мае вельмі просты api, які дазваляе ствараць скрыншоты з зададзенага URL:

імпартаваць вэб-файл з "webshot";

webshot ('https://chatilyzer.com', 'chat.png', function (памылка) {
  // Скрыншот зараз захаваны ў chat.png
});

Пасля стварэння скрыншота мне трэба было загрузіць яго ў хмарнае сховішча і адправіць назад URL малюнка на бок кліента, каб я мог дазволіць карыстачу загружаць выяву.

Плюсы:

  • Гатовы да выкарыстання модуль.
  • Здымак экрана захоўваецца ў воблаку, каб ён быў даступны ў любы час.
  • Гнуткі api, які дазваляе ўсталяваць патрэбную шырыню і вышыню скрыншота.

Мінусы:

  • Усё ці нічога - скрыншот захоплівае ўсю старонку, і вы не можаце кіраваць канкрэтным элементам, які вы хочаце захаваць.
  • Візуалізацыя - Калі вам трэба дачакацца загрузкі асінхроннага файла, перш чым зрабіць скрыншот, у вас могуць узнікнуць праблемы.
  • Навакольнае асяроддзе - Улічваючы, што вы не знаходзіцеся ў рэальным асяроддзі браўзэра, PhantomJS не апрацоўвае карыстацкія / Google шрыфты як належныя, што прыводзіць да шрыфта па змаўчанні, які адлюстроўваецца на вашым скрыншоце.
  • Захоўванне - Пасля стварэння скрыншота неабходна захаваць яго ў воблачным сховішчы, каб вярнуць карыстачу сапраўдны URL-адрас малюнка. Гэта значыць, вам патрэбен пастаўшчык хмарных сховішчаў, які патэнцыйна можа каштаваць вам больш грошай.
  • Бяспека - калі дадзеныя скрыншота адчувальныя, захаванне копіі ў воблаку - не добры падыход.

EDIT: Пасля атрымання зваротнай сувязі з супольнасцю аказваецца, што ёсць яшчэ адно сервернае рашэнне з выкарыстаннем модуля NPM пад назвай "Puppeteer", які працуе на верхняй частцы Chrome без галавы. Вось як стварыць скрыншот з Puppeteer:

const puppeteer = патрабаваць ('лялечнік');

(async () => {
  const browser = чакаць puppeteer.launch ();
  старонка const = чакаць browser.newPage ();
  чакаць page.goto ('https://chatilyzer.com');
  чакаць page.screenshot ({шлях: 'chatilyzer.png'});

  чакаць browser.close ();
}) ();

Гэты модуль будзе вырашаць усе альбо нічога, праблемы рэндэрынгу і навакольнага асяроддзя, паколькі ён забяспечвае той жа рухавік візуалізацыі, што і Chrome.

Кліентскі падыход

Я не знайшоў вынік падыходу сервернага боку дастаткова добры для майго выкарыстання, таму пачаў вывучаць іншыя варыянты.

Я знайшоў надзвычай класную бібліятэку JS пад назвай "html2canvas", якая, як вынікае з назвы, ператворыць HTML-элемент у элемент канва.

вэб-сайт html2canvas

Як бачыце, ён таксама вельмі просты ў выкарыстанні. У асноўным вы называеце метад html2canvas і перадаеце элемент DOM як аргумент. Гэты метад вяртае абяцанне, якое вы можаце выкарыстоўваць для здабывання элемента палатна.

html2canvas (document.querySelector ("# захоп")). Затым (canvasElm => {
    document.body.appendChild (canvasElm);
});

Далей вы хочаце ўключыць карыстачу загрузку скрыншота.

Як зрабіць гэта з дапамогай метаду JS toDataURL, як вы можаце бачыць ніжэй:

// Атрымаць радок дадзеных base64
var imageType = 'image / 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).
  • Падтрымка элементаў - У html2canvas не падтрымліваюцца ўсе элементы HTML. Напрыклад, іншыя элементы палатна, кадры і ўспышка не будуць адлюстроўвацца наогул.

У заключэнні

Ёсць два падыходы, як зрабіць скрыншот з html-элементаў, і вы павінны падумаць, што падыходзіць вашаму дадатку.

Падыход з боку сервера - гэта той, які вы выбіраеце, калі вам патрэбен крос-аглядальнік / платформа, і не ўпэўнены, што вашы карыстальнікі будуць мець патрэбны браўзэр для таго, каб зрабіць скрыншот. Кошт, якую вы павінны будзеце заплаціць, азначае як фізічную аплату за паслугу хмарных сховішчаў, так і недакладныя вынікі.

Кліентскі падыход добры, калі вы ўпэўненыя, што ў вашых карыстальнікаў з'явіўся браўзэр, здольны зрабіць скрыншот (альбо вы гатовы заплаціць цану тым, хто гэтага не робіць), і калі для скрыншота неабходная дакладнасць.

Хуткая думка - я мяркую, што найлепшым падыходам будзе аб'яднанне паміж імі. Вы можаце праверыць, ці ёсць у сумяшчальнасці браўзэра карыстальніка падтрымка, якая вам патрэбна для таго, каб зрабіць скрыншот, а калі няма, то назад да падыходу з боку сервера.

Спадзяюся, вам спадабаўся артыкул. Пляскайце, вам спадабалася :)

Ці ведаеце вы пра іншыя спосабы стварэння скрыншотаў вэб-старонак з дапамогай NodeJS? Падзяліся ў каментарах!