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

[1.12] Add the ability to screenshot individual elements on the page #553

Merged
merged 9 commits into from
Nov 6, 2024
Merged
37 changes: 20 additions & 17 deletions src/Clip.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,23 @@

class Clip
{
/** @var int|float */
protected $x;
/** @var int|float */
protected $y;
/** @var int|float */
protected $height;
/** @var int|float */
protected $width;
/** @var float */
protected $scale;

/**
* Clip constructor.
*
* @param int $x
* @param int $y
* @param int $height
* @param int $width
* @param float $scale
* @param int|float $x
* @param int|float $y
* @param int|float $height
* @param int|float $width
* @param float $scale
*/
public function __construct($x, $y, $width, $height, $scale = 1.0)
{
Expand All @@ -38,79 +41,79 @@ public function __construct($x, $y, $width, $height, $scale = 1.0)
}

/**
* @return mixed
* @return int|float
*/
public function getX()
{
return $this->x;
}

/**
* @return mixed
* @return int|float
*/
public function getY()
{
return $this->y;
}

/**
* @return mixed
* @return int|float
*/
public function getHeight()
{
return $this->height;
}

/**
* @return mixed
* @return int|float
*/
public function getWidth()
{
return $this->width;
}

/**
* @return mixed
* @return float
*/
public function getScale()
{
return $this->scale;
}

/**
* @param mixed $x
* @param int|float $x
*/
public function setX($x): void
{
$this->x = $x;
}

/**
* @param mixed $y
* @param int|float $y
*/
public function setY($y): void
{
$this->y = $y;
}

/**
* @param mixed $height
* @param int $height
*/
public function setHeight($height): void
{
$this->height = $height;
}

/**
* @param mixed $width
* @param int $width
*/
public function setWidth($width): void
{
$this->width = $width;
}

/**
* @param mixed $scale
* @param float $scale
*/
public function setScale($scale): void
{
Expand Down
19 changes: 18 additions & 1 deletion src/Dom/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace HeadlessChromium\Dom;

use HeadlessChromium\Clip;
use HeadlessChromium\Communication\Message;
use HeadlessChromium\Communication\Response;
use HeadlessChromium\Exception\DomException;
Expand Down Expand Up @@ -177,7 +178,7 @@ public function click(): void
$this->scrollIntoView();
$position = $this->getPosition();
$this->page->mouse()
->move($position->getCenterX(), $position->getCenterY())
->move((int) $position->getCenterX(), (int) $position->getCenterY())
->click();
}

Expand Down Expand Up @@ -214,4 +215,20 @@ public function assertNotError(Response $response): void
throw new DOMException($response->getErrorMessage());
}
}

public function getClip(): ?Clip
{
$position = $this->getPosition();

if (!$position) {
return null;
}

return new Clip(
$position->getX(),
$position->getY(),
$position->getWidth(),
$position->getHeight(),
);
}
}
32 changes: 16 additions & 16 deletions src/Dom/NodePosition.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,40 +37,40 @@ public function __construct(array $points)
$leftBottomX = $points[6];
$leftBottomY = $points[7];

$this->x = $leftTopX;
$this->y = $leftTopY;
$this->x = (float) $leftTopX;
$this->y = (float) $leftTopY;

$this->height = $leftBottomY - $leftTopY;
$this->width = $rightBottomX - $leftBottomX;
$this->height = (float) ($leftBottomY - $leftTopY);
$this->width = (float) ($rightBottomX - $leftBottomX);
}

public function getX(): int
public function getX(): float
{
return (int) $this->x;
return $this->x;
}

public function getY(): int
public function getY(): float
{
return (int) $this->y;
return $this->y;
}

public function getWidth(): int
public function getWidth(): float
{
return (int) $this->width;
return $this->width;
}

public function getHeight(): int
public function getHeight(): float
{
return (int) $this->height;
return $this->height;
}

public function getCenterX(): int
public function getCenterX(): float
{
return (int) ($this->x + ($this->width / 2));
return $this->x + ($this->width / 2);
}

public function getCenterY(): int
public function getCenterY(): float
{
return (int) ($this->y + ($this->height / 2));
return $this->y + ($this->height / 2);
}
}
8 changes: 8 additions & 0 deletions src/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use HeadlessChromium\Cookies\Cookie;
use HeadlessChromium\Cookies\CookiesCollection;
use HeadlessChromium\Dom\Dom;
use HeadlessChromium\Dom\Node;
use HeadlessChromium\Dom\Selector\CssSelector;
use HeadlessChromium\Dom\Selector\Selector;
use HeadlessChromium\Exception\CommunicationException;
Expand Down Expand Up @@ -673,6 +674,13 @@ public function screenshot(array $options = []): PageScreenshot
return new PageScreenshot($responseReader);
}

public function screenshotElement(Node $node): PageScreenshot
{
return $this->screenshot([
'clip' => $node->getClip(),
]);
}

/**
* Generate a PDF
* Usage:.
Expand Down
16 changes: 16 additions & 0 deletions tests/PageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -507,4 +507,20 @@ public function testSetScriptExecution(): void
$page->evaluate('document.body.innerText')->getReturnValue()
);
}

public function testElementScreenshot(): void
{
$factory = new BrowserFactory();

$browser = $factory->createBrowser();
$page = $browser->createPage();

$page->navigate($this->sitePath('domForm.html'))->waitForNavigation();

$element = $page->dom()->querySelector('#myform');
$screenshot = $page->screenshotElement($element);

self::assertNotEmpty($screenshot->getBase64());
self::assertGreaterThan(4000, \strlen($screenshot->getBase64()));
}
}
Loading