1

I am trying to take a screenshot of an svg element, but am only getting a partial picture. What am I doing wrong ?

'use strict';

const puppeteer = require('puppeteer');

(async () => {
       const browser = await puppeteer.launch();

       try {
           const page = await browser.newPage();
           await page.goto('https://jisho.org/search/%E5%AE%B6%20%23kanji');

           const selector = '#result_area > div > div:nth-child(2) > div.small-12.large-10.columns > div > div > div > svg';
           await page.waitForSelector(selector);
           const element = await page.$(selector); 

           await element.screenshot({
               path: 'example.png',            
           });
       } catch (e) {
           console.log(e)
       } finally {
           await browser.close();
       }
})();
ggorlen
  • 44,755
  • 7
  • 76
  • 106
Sheet
  • 13
  • 5
  • Why are you trying to screenshot an SVG? I would just save the SVG element as text so it's still an SVG. You can always rasterize it to png later. – ggorlen Sep 08 '22 at 21:09

1 Answers1

1

If it were me, I'd just save the SVG directly rather than converting it to a PNG. This preserves the scalability and raw data without quality loss and you can always convert to PNG later.

But if you really want a PNG only and you want a pure Puppeteer solution, the issue is that overflow-x: hidden CSS is on the parent container of the SVG, and the overall page layout makes it fussy to screenshot.

So I'd just rip out all of the page HTML except for the one element you're interested in. This makes it much easier to capture.

const puppeteer = require("puppeteer"); // ^19.7.2

let browser;
(async () => {
  browser = await puppeteer.launch({headless: true});
  const [page] = await browser.pages();
  const url = "https://jisho.org/search/%E5%AE%B6%20%23kanji";
  await page.goto(url, {waitUntil: "domcontentloaded"});
  const sel = ".stroke_order_diagram--outer_container svg";
  const el = await page.waitForSelector(sel);
  const svg = await el.evaluateHandle(el => {
    document.body.innerHTML = el.outerHTML;
    return document.querySelector("svg");
  });
  await svg.screenshot({path: "example.png"});
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close());
ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • thanks alot ! i was only trying to take a screenshot because i havent figured out how to save the svg – Sheet Sep 08 '22 at 21:43
  • It's easy to save (write the SVG string to a file with `fs.writeFile`), but it turns out after doing so the SVG isn't valid out of the box due to an [undefined namespace prefix](https://stackoverflow.com/questions/36183667/namespace-prefix-isnt-defined-how-can-i-define-it-automatically-ignore-error). Turns out it's [KanjiVG](https://kanjivg.tagaini.net/index.html) and I don't know enough about SVG to figure out how to open it easily. Feel free to add an answer if you figure it out. – ggorlen Sep 08 '22 at 22:09