Zachycení Screenshotů prvků DOM: Server Side VS. Přístupy na straně klienta

Před několika týdny jsem psal o Chatilyzerovi - novém vedlejším projektu, na kterém jsem pracoval minulý měsíc.

Rychlý přehled o aplikaci a průběhu aplikace: Chatilyzer vám umožňuje získat statistiky o vašich chatech WhatsApp. Aby aplikace fungovala, musíte nahrát exportovaný soubor * .txt z chatu WhatsApp. Chatilyzer analyzuje a analyzuje text a extrahuje z něj některá zajímavá data. Poté budete přesměrováni na stránku s výsledky, kde uvidíte pěknou vizualizaci aktivity vašeho chatu.

Příklad stránky s výsledky Chatilyzer

Jednou z výzev, které jsem měl při vývoji této webové aplikace, bylo umožnit uživatelům vytvořit screenshot stránky s výsledky a stáhnout si ji, aby ji mohli sdílet ve své skupině - místo sdílení adresy URL stránky.

Přístup na straně serveru (NodeJS)

Začal jsem s přístupem na straně serveru pomocí PhantomJS a modulu NPM s názvem „Node Webshot“. Má velmi jednoduché API, které vám umožní vytvářet screenshoty z dané adresy URL:

importovat webshot z 'webshot';

webshot ('https://chatilyzer.com', 'chat.png', function (err) {
  // screenshot je nyní uložen do chat.png
});

Po vytvoření snímku jsem ho potřeboval nahrát do cloudového úložiště a poslat zpět URL obrázku na stranu klienta, abych mohl uživateli dovolit obrázek stáhnout.

Klady:

  • Modul připravený k použití.
  • Snímek obrazovky se ukládá do cloudu, takže je kdykoli k dispozici.
  • Flexibilní API, které vám umožní nastavit požadovanou šířku a výšku snímku obrazovky.

Nevýhody:

  • Vše nebo nic - snímek obrazovky zachycuje celou stránku a nemůžete ovládat konkrétní prvek, který chcete zachytit.
  • Vykreslování - Pokud potřebujete počkat, než se načte asynchronní JS, než pořídíte snímek obrazovky, můžete narazit na problémy.
  • Prostředí - Vzhledem k tomu, že nejste ve skutečném prostředí prohlížeče, PhantomJS nezpracovává vlastní písma / písma Google správně, což vede k výchozímu písmu, které je vykresleno na snímku obrazovky.
  • Úložiště - Po vytvoření snímku je nutné jej uložit do cloudového úložiště, abyste uživateli mohli vrátit platnou adresu URL obrázku. To znamená, že potřebujete poskytovatele cloudového úložiště, který by vás mohl stát dražší.
  • Zabezpečení - Pokud jsou data snímku obrazovky citlivá, uložení kopie do cloudu není dobrý přístup.

ÚPRAVA: Po získání zpětné vazby od komunity se ukáže, že existuje další řešení na straně serveru pomocí modulu NPM s názvem „Puppeteer“, který běží na vrcholu bezhlavého Chrome. Zde je návod, jak vytvořit screenshot s Puppeteer:

const puppeteer = vyžadovat ('loutkář');

(async () => {
  const browser = await puppeteer.launch ();
  const page = await browser.newPage ();
  čekat page.goto ('https://chatilyzer.com');
  čekejte page.screens ({path: 'chatilyzer.png'});

  čekat prohlížeč.close ();
}) ();

Tento modul by vyřešil problémy typu Vše nebo nic, vykreslování a prostředí, protože poskytuje stejný modul vykreslování jako Chrome.

Přístup na straně klienta

Výsledek přístupu na straně serveru nebyl pro můj případ použití dostatečně dobrý, takže jsem začal zkoumat další možnosti.

Našel jsem extrémně cool knihovnu JS s názvem „html2canvas“, která, jak název napovídá, změní prvek HTML na prvek plátno.

html2canvas web

Jak vidíte, je také velmi snadné použití. V zásadě voláte metodu html2canvas a jako argument předáváte prvek DOM. Tato metoda vrací slib, který můžete použít k extrahování prvku plátna.

html2canvas (document.querySelector ("# capt")). then (canvasElm => {
    document.body.appendChild (canvasElm);
});

Dále chcete uživateli povolit stahování snímku obrazovky.

Způsob, jak toho dosáhnout, je pomocí metody JS toDataURL, jak vidíte níže:

// Získat datový řetězec base64
var imageType = 'image / png';
var imageData = canvasElm.toDataURL (imageType);
// Otevřete datový řetězec v aktuálním okně
document.location.href = imageData.replace (imageType, 'image / octet-stream');

Existuje další knihovna JS s názvem „canvas2image“. Doporučuji ji spíše psát sami, protože poskytuje větší flexibilitu a také umožňuje generovat značku obrázku z prvku plátno. Můžete tedy dosáhnout stejného výsledku pomocí:

Canvas2Image.saveAsPNG (canvasElm, width, height);

Klady:

  • WYSIWYG - Výsledkem je 1: 1 toho, co vidíte na obrazovce.
  • Žádná strana serveru - Vše spuštěné v prohlížeči.
  • Zabezpečení - Pokud jsou data snímku obrazovky citlivá, zachyťte je na straně klienta mnohem bezpečněji, protože server si není vědom výsledků a nikde neukládejte kopii.

Nevýhody:

  • Kompatibilita - html2canvas není podporován ve všech prohlížečích
  • Drahé - Přestože html2canvas vrací slib, je to stále drahá akce a u velkých a komplikovaných komponent může trvat několik sekund, než se dostaví výsledky.
  • Úzké zobrazení - Pokud používáte úzkou obrazovku (například v mobilu), bude snímek obrazovky úzký a bude zachycovat snímek ze skutečného pohledu (to lze vyřešit buď předáním šířky opravy jako argumentu canvas2html , nebo otevřením prvku iframe s požadovanou šířkou na pozadí, pořiďte snímek obrazovky a odešlete zpět obrazová data s postMessage).
  • Podpora prvků - v html2canvas nejsou podporovány všechny prvky html. Například jiné prvky plátna, prvky iframe a flash nebudou vykresleny vůbec.

Závěrem

Existují dva způsoby, jak zachytit snímek obrazovky z prvků html, a měli byste si myslet, co vyhovuje vaší aplikaci.

Přístup na straně serveru je ten, který vyberete, když potřebujete zkušenost s křížovým prohlížečem / platformou, a není si jistý, že vaši uživatelé budou mít ten správný prohlížeč, aby mohli zachytit snímek obrazovky. Cena, kterou budete muset zaplatit, je jak fyzická platba za službu cloudového úložiště, tak nepřesné výsledky.

Přístup na straně klienta je dobrý, pokud jste si jisti, že vaši uživatelé budou mít prohlížeč, který je schopen zachytit snímek obrazovky (nebo jste připraveni zaplatit cenu za ty, kteří tak neučiní), a když je přesnost snímku nutná.

Rychlá myšlenka - myslím, že nejlepší přístup bude kombinovat mezi nimi. Můžete zkontrolovat, zda má kompatibilita prohlížeče kompatibilitu, kterou potřebujete, aby bylo možné zachytit snímek obrazovky, a pokud ne, záložní přístup na straně serveru.

Doufám, že se vám článek líbil. Clap to se vám líbilo :)

Víte o jiných způsobech vytváření screenshotů webových stránek pomocí NodeJS? Sdílet v komentářích!