Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Screenshot an area of interest #306

Closed
przemyslawpluta opened this issue Aug 16, 2017 · 11 comments
Closed

Screenshot an area of interest #306

przemyslawpluta opened this issue Aug 16, 2017 · 11 comments

Comments

@przemyslawpluta
Copy link

przemyslawpluta commented Aug 16, 2017

It would be great if there would be an option to be able to screenshot an area of interest something like:

window.selectArea(x, y, w, h)

screen shot 2017-08-16 at 22 03 23

Then ...

page.screenshotArea({path: 'example.png'})

... and you'd end up with selected area only e.g.

screen shot 2017-08-16 at 22 05 00

So we'd scroll to the point and draw an area or interest for screenshot. Any plans for this type of behaviour?

@JoelEinbinder
Copy link
Collaborator

Screenshot takes a clip rectangle. You can use page.exposeFunction to add a screenshotArea function onto the window object of your page.

@ebidel
Copy link
Contributor

ebidel commented Aug 16, 2017

Here's an example of taking a screenshot of a dom element, the logo on chromestatus.com:

// adjustments for this page (so we hit the desktop breakpoint)
page.setViewport({width: 1000, height: 600, deviceScaleFactor: 2});

await page.goto('https://www.chromestatus.com/samples', {waitUntil: 'networkidle'});

async function screenshotDOMElement(selector, padding = 0) {
  const rect = await page.evaluate(selector => {
    const element = document.querySelector(selector);
    const {x, y, width, height} = element.getBoundingClientRect();
    return {left: x, top: y, width, height, id: element.id};
  }, selector);

  return await page.screenshot({
    path: 'element.png',
    clip: {
      x: rect.left - padding,
      y: rect.top - padding,
      width: rect.width + padding * 2,
      height: rect.height + padding * 2
    }
  });
}

await screenshotDOMElement('header aside', 16);

@przemyslawpluta
Copy link
Author

przemyslawpluta commented Aug 17, 2017

@ebidel thanks for this example. It's getting there but one issue with this is that you have to know the SELECTOR my example assumes that you don't know anything about the SELECTOR but you do know the coordinates on the page you'd like to see also the area you might want to screenshot might span across different elements of the website.

@ebidel
Copy link
Contributor

ebidel commented Aug 17, 2017

Sure, just modify the snippet to take the coordinates directly :)

@przemyslawpluta
Copy link
Author

@ebidel indeed ...

    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    page.setViewport({ width: 1000, height: 600, deviceScaleFactor: 2 });
    await page.goto('https://www.chromestatus.com/samples', { waitUntil: 'networkidle' });
    await page.screenshot({
        path: 'element.png',
        clip: {x: 215, y: 0, width: 390, height: 50}
    });
    browser.close();

@wong2
Copy link

wong2 commented Oct 15, 2017

@ebidel why not add an selector option to screenshot api based on your screenshotDOMElement function?

@ebidel
Copy link
Contributor

ebidel commented Oct 15, 2017 via email

@MManchukonda
Copy link

Here's an example of taking a screenshot of a dom element, the logo on chromestatus.com:

// adjustments for this page (so we hit the desktop breakpoint)
page.setViewport({width: 1000, height: 600, deviceScaleFactor: 2});

await page.goto('https://www.chromestatus.com/samples', {waitUntil: 'networkidle'});

async function screenshotDOMElement(selector, padding = 0) {
  const rect = await page.evaluate(selector => {
    const element = document.querySelector(selector);
    const {x, y, width, height} = element.getBoundingClientRect();
    return {left: x, top: y, width, height, id: element.id};
  }, selector);

  return await page.screenshot({
    path: 'element.png',
    clip: {
      x: rect.left - padding,
      y: rect.top - padding,
      width: rect.width + padding * 2,
      height: rect.height + padding * 2
    }
  });
}

await screenshotDOMElement('header aside', 16);

How to take screenshot for Xpath?

@SuciuCalin
Copy link

Here's an example of taking a screenshot of a dom element, the logo on chromestatus.com:

// adjustments for this page (so we hit the desktop breakpoint)
page.setViewport({width: 1000, height: 600, deviceScaleFactor: 2});

await page.goto('https://www.chromestatus.com/samples', {waitUntil: 'networkidle'});

async function screenshotDOMElement(selector, padding = 0) {
  const rect = await page.evaluate(selector => {
    const element = document.querySelector(selector);
    const {x, y, width, height} = element.getBoundingClientRect();
    return {left: x, top: y, width, height, id: element.id};
  }, selector);

  return await page.screenshot({
    path: 'element.png',
    clip: {
      x: rect.left - padding,
      y: rect.top - padding,
      width: rect.width + padding * 2,
      height: rect.height + padding * 2
    }
  });
}

await screenshotDOMElement('header aside', 16);

How to take screenshot for Xpath?

This worked for me:

    /**
    * Selecting the element by xpath
    * page.$x() returns an array of ElementHandle.
    * We are only interested in the first element
    **/
    const elByXpath = (await page.$x(req.param('elXpath')))[0]

    const rect = await page.evaluate(element => {
        if (!element)
            return null;
        const {x, y, width, height} = element.getBoundingClientRect();
        return {left: x, top: y, width, height};
    }, elByXpath);

@mdshihabullah
Copy link

    const elByXpath = (await page.$x(req.param('elXpath')))[0]

    const rect = await page.evaluate(element => {
        if (!element)
            return null;
        const {x, y, width, height} = element.getBoundingClientRect();
        return {left: x, top: y, width, height};
    }, elByXpath);

Not working!

@tarkungZZ
Copy link

Here's an example of taking a screenshot of a dom element, the logo on chromestatus.com:

// adjustments for this page (so we hit the desktop breakpoint)
page.setViewport({width: 1000, height: 600, deviceScaleFactor: 2});

await page.goto('https://www.chromestatus.com/samples', {waitUntil: 'networkidle'});

async function screenshotDOMElement(selector, padding = 0) {
  const rect = await page.evaluate(selector => {
    const element = document.querySelector(selector);
    const {x, y, width, height} = element.getBoundingClientRect();
    return {left: x, top: y, width, height, id: element.id};
  }, selector);

  return await page.screenshot({
    path: 'element.png',
    clip: {
      x: rect.left - padding,
      y: rect.top - padding,
      width: rect.width + padding * 2,
      height: rect.height + padding * 2
    }
  });
}

await screenshotDOMElement('header aside', 16);

I'm using this it work well with selector outside frame or iframe but it can't find selector in frame or iframe.

Can you fix it for me pls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants