问题描述
我创建了一个工具,可以在许多桌面和设备配置的 URL 列表上截取整页屏幕截图。在桌面设备上,这一切都运行良好,我可以在所有浏览器和操作系统版本上恢复整页屏幕截图。
尝试在移动设备上执行此操作时会出现问题,我猜这是由于我正在运行的设备的像素比造成的。
我的方法获取页面的总高度和宽度,以及视口的高度和宽度,基本上获取视口的图像,在必要时滚动,然后最后将所有这些拼接成一个图像。
但是,使用我通过 JavaScript 检索的像素比,屏幕截图永远无法正确捕获,也无法正确滚动和/或无法捕获整个页面。横向是可以的,它总是高度。就像它在错误地计算滚动
我无法在网上的任何地方找到与遇到相同或类似问题的人的任何帖子,这让我感到震惊。所以要么我把它复杂化了,它是如此微不足道以至于它从来不需要一个帖子,要么这比我想象的要困难得多,人们没有充分的理由这样做
如果有人有任何想法或想法,他们将非常感激
谢谢!
public Image GetEntireScreenshot(ArrayList hiddenElementListAfterFirstViewport = null,bool isMobile = false)
{
var pixelRatio = 1;
if (isMobile) pixelRatio = (int) (long) ((IJavaScriptExecutor) driver).ExecuteScript("return window.devicePixelRatio");
// Size of page
var totalWidth = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.offsetWidth") * pixelRatio);
var totalHeight = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.parentNode.scrollHeight") * pixelRatio);
// Size of the viewport
var viewportWidth = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.clientWidth") * pixelRatio);
var viewportHeight = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return window.innerHeight") * pixelRatio);
var screenshot = (ITakesScreenshot)driver;
((IJavaScriptExecutor)driver).ExecuteScript("window.scrollTo(0,0)");
if (hiddenElementListAfterFirstViewport != null)
{
foreach (string hiddenElementXPath in hiddenElementListAfterFirstViewport)
{
IList<IWebElement> elements = driver.FindElements(By.XPath(hiddenElementXPath));
foreach (var element in elements)
{
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].style.visibility='hidden'",element);
}
}
}
if (totalWidth <= viewportWidth && totalHeight <= viewportHeight) return ScreenshottoImage(screenshot.GetScreenshot());
var rectangles = new List<Rectangle>();
// Loop until the totalHeight is reached
for (var y = 0; y < totalHeight; y += viewportHeight)
{
var newHeight = viewportHeight;
// Fix if the height of the element is too big
if (y + viewportHeight > totalHeight) newHeight = totalHeight - y;
// Loop until the totalWidth is reached
for (var x = 0; x < totalWidth; x += viewportWidth)
{
var newWidth = viewportWidth;
// Fix if the Width of the Element is too big
if (x + viewportWidth > totalWidth) newWidth = totalWidth - x;
// Create and add the Rectangle
rectangles.Add(new Rectangle(x,y,newWidth,newHeight));
}
}
var stitchedImage = new Bitmap(totalWidth,totalHeight);
var prevIoUs = Rectangle.Empty;
foreach (var rectangle in rectangles)
{
// Calculate scrolling (if needed)
if (prevIoUs != Rectangle.Empty) ((IJavaScriptExecutor) driver).ExecuteScript($"window.scrollBy({rectangle.Right - prevIoUs.Right},{rectangle.Bottom - prevIoUs.Bottom})");
// Calculate the source Rectangle
var sourceRectangle = new Rectangle(viewportWidth - rectangle.Width,viewportHeight - rectangle.Height,rectangle.Width,rectangle.Height);
// copy the Image
using (var graphics = Graphics.FromImage(stitchedImage))
{
graphics.DrawImage(ScreenshottoImage(screenshot.GetScreenshot()),rectangle,sourceRectangle,GraphicsUnit.Pixel);
}
prevIoUs = rectangle;
}
return stitchedImage;
}
解决方法
您可以使用 ShutterBug 等工具在移动设备上捕获整页屏幕截图,http://automationtesting.in/take-full-page-screenshot-using-shutterbug/
,我解决了这个问题的问题,如果有同样问题的人看到这篇文章,就在此发帖:
问题在于代码的滚动部分:
if (previous != Rectangle.Empty) ((IJavaScriptExecutor) driver).ExecuteScript($"window.scrollBy({rectangle.Right - previous.Right},{rectangle.Bottom - previous.Bottom})");
我正在滚动之前乘以像素比率量的值,这意味着它们太多了,因为滚动 X 和 Y 值不受设备像素比率的影响。
因此,代码应该是:
if (previous != Rectangle.Empty) ((IJavaScriptExecutor) driver).ExecuteScript($"window.scrollBy({(rectangle.Right - previous.Right) / pixelRatio},{(rectangle.Bottom - previous.Bottom) / pixelRatio})");