将网页保存为 PNG 图像
要截取指定网页的屏幕截图,您需要执行以下步骤:
- 创建浏览器实例。
- 设置所需的浏览器大小。
- 使用此 Browser 实例创建一个 BrowserView(WPF 或 WinForms)
- 通过 URL 或 HTML 加载所需的网页,并等待其内容完全呈现。
- 使用 BrowserView.GetImage() 获取加载网页的 System Drawing.Image。
注意:以下示例中使用的 OnRepaint 事件仅支持轻量级渲染模式。GetImage() 方法适用于两种模式,但在调用此方法之前应嵌入并显示组件。
例子
以下示例演示如何捕获完整网页的图像。在这种情况下,您甚至不需要嵌入浏览器视图。
using DotNetBrowser;
using DotNetBrowser.Events;
using DotNetBrowser.WPF;
using System;
using System.Drawing.Imaging;
using System.Threading;
using System.Windows;
namespace HTMLToImageSample
{
public partial class WindowMain : Window
{
private WPFBrowserView browserView;
public WindowMain()
{
this.Loaded += delegate
{
Width = 400;
Height = 300;
browserView = new WPFBrowserView(BrowserFactory.Create(BrowserType.LIGHTWEIGHT));
Browser browser = browserView.Browser;
// #1 Set browser initial size
browserView.Browser.SetSize(1280, 1024);
// #2 Load web page and wait until web page is loaded completely.
ManualResetEvent resetEvent = new ManualResetEvent(false);
FinishLoadingFrameHandler listener = new FinishLoadingFrameHandler((object sender, FinishLoadingEventArgs e) =>
{
if (e.IsMainFrame)
{
resetEvent.Set();
}
});
browser.FinishLoadingFrameEvent += listener;
try
{
browser.LoadURL("teamdev.com/dotnetbrowser");
resetEvent.WaitOne(new TimeSpan(0, 0, 45));
}
finally
{
browser.FinishLoadingFrameEvent -= listener;
}
// #3 Set the required document size.
JSValue documentHeight = browserView.Browser.ExecuteJavaScriptAndReturnValue(
"Math.max(document.body.scrollHeight, " +
"document.documentElement.scrollHeight, document.body.offsetHeight, " +
"document.documentElement.offsetHeight, document.body.clientHeight, " +
"document.documentElement.clientHeight);");
JSValue documentWidth = browserView.Browser.ExecuteJavaScriptAndReturnValue(
"Math.max(document.body.scrollWidth, " +
"document.documentElement.scrollWidth, document.body.offsetWidth, " +
"document.documentElement.offsetWidth, document.body.clientWidth, " +
"document.documentElement.clientWidth);");
int scrollBarSize = 25;
int viewWidth = (int)documentWidth.GetNumber() + scrollBarSize;
int viewHeight = (int)documentHeight.GetNumber() + scrollBarSize;
// #4 Register OnRepaint to get notifications
// about paint events. We expect that web page will be completely rendered twice:
// 1. When its size is updated.
// 2. When HTML content is loaded and displayed.
ManualResetEvent waitEvent = new ManualResetEvent(false);
DrawingView drawingView = (DrawingView)browserView.GetInnerView();
drawingView.OnRepaint += delegate(object sender, OnRepaintEventArgs e)
{
// Make sure that all view content has been repainted.
if (e.UpdatedRect.Size.Equals(e.ClientSize))
{
waitEvent.Set();
}
};
browserView.Browser.SetSize(viewWidth, viewHeight);
// #5 Wait until Chromium renders web page content.
waitEvent.WaitOne();
// #6 Save Image of the loaded web page into a PNG file.
Dispatcher.BeginInvoke((Action)(() =>
{
browserView.GetImage().Save(@"teamdev.png", ImageFormat.Png);
}));
};
}
[STAThread]
public static void Main()
{
Application app = new Application();
WindowMain wnd = new WindowMain();
app.Run(wnd);
var browser = wnd.browserView.Browser;
wnd.browserView.Dispose();
browser.Dispose();
}
}
}
计算页面大小
如果您需要截取整个网页的截图,包括可滚动的隐藏部分,并且您不知道网页的尺寸,则需要使用以下方法进行计算:
JSValue documentHeight = browser.ExecuteJavaScriptAndReturnValue(
"Math.max(document.body.scrollHeight, " +
"document.documentElement.scrollHeight, document.body.offsetHeight, " +
"document.documentElement.offsetHeight, document.body.clientHeight, " +
"document.documentElement.clientHeight);");
JSValue documentWidth = browser.executeJavaScriptAndReturnValue(
"Math.max(document.body.scrollWidth, " +
"document.documentElement.scrollWidth, document.body.offsetWidth, " +
"document.documentElement.offsetWidth, document.body.clientWidth, " +
"document.documentElement.clientWidth);");
int scrollBarSize = 25;
int viewWidth = (int) documentWidth.GetNumber() + scrollBarSize;
int viewHeight = (int) documentHeight.GetNumber() + scrollBarSize;
在这段代码中,我们使用 JavaScript 和 DOM API 来获取加载文档的尺寸。
完整的示例解决方案可以在本文的附件中找到。此解决方案中的项目具有 NuGet 依赖项,将在构建过程中自动解析。
捕获长页面
如果您尝试捕获长网页,您可能已经注意到图像被剪切为非常长的页面。这种行为是由 Chromium 本身内部的限制引起的。Chromium 在最大高度设置为 16384 的画布上渲染网页的内容。如果网页的高度超过最大纹理大小,则在 Chromium 画布之外的网页部分将不会被绘制,并且会被填充为黑色。要解决此限制并捕获高度超过最大纹理大小的网页的完整图像,您应该在创建任何 Browser 或 BrowserView 实例之前指定以下开关:
int viewWidth = 1024;
int viewHeight = 20000;
string[] switches = {
"--disable-gpu",
"--max-texture-size=" + viewHeight
};
BrowserPreferences.SetChromiumSwitches(switches);
如果指定了这些开关,GPU 进程将被禁用,并且 Chromium 最大纹理大小将从 16384 更改为 viewHeight。
注意: --max-texture-size 开关是在 DotNetBrowser 1.9 中引入的。