我使用Chart.js在我的前端ASP.NET应用程序上显示图表。现在我需要在后端生成PNG文件。是否可以在没有Web浏览器的情况下渲染画布?我应该使用哪种技术?
答案 0 :(得分:1)
以下是我在类似情况下使用的一些代码,它采用了一些html并生成了它的图像(裁剪空白)。我不确定在页面生命周期中Chart.js何时绘制它的图表但是这可能不起作用。您可以调整它以加载实际页面而不是传入HTML。
不漂亮,不是平台无关,并且可能会有不同的结果,具体取决于IE等的版本(特别是考虑到Chart.js需要IE上的polyfill< = 8)。但它适用于我需要它的情况。
public class HtmlToImageConverter
{
public string Html { get; set; }
public Bitmap Image { get; set; }
public HtmlToImageConverter(string html)
{
this.Html = html;
}
public Bitmap Render()
{
var thread = new Thread(GenerateInternal);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
return Image;
}
private void GenerateInternal()
{
var webBrowser = new WebBrowser
{
ScrollBarsEnabled = false,
DocumentText = this.Html,
ClientSize = new Size(3000, 3000)
};
webBrowser.DocumentCompleted += WebBrowser_DocumentCompleted;
while (webBrowser.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents();
webBrowser.Dispose();
}
private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var webBrowser = (WebBrowser)sender;
this.Image = new Bitmap(webBrowser.Bounds.Width, webBrowser.Bounds.Height);
webBrowser.BringToFront();
webBrowser.DrawToBitmap(Image, webBrowser.Bounds);
this.Image = AutoCrop(this.Image);
}
private static byte[][] GetRgb(Bitmap bmp)
{
var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
var ptr = bmpData.Scan0;
var numPixels = bmp.Width * bmp.Height;
var numBytes = bmpData.Stride*bmp.Height;
var padding = bmpData.Stride - bmp.Width*3;
var i = 0;
var ct = 1;
var r = new byte[numPixels];
var g = new byte[numPixels];
var b = new byte[numPixels];
var rgb = new byte[numBytes];
Marshal.Copy(ptr, rgb, 0, numBytes);
for (var x = 0; x < numBytes - 3; x += 3)
{
if (x == (bmpData.Stride*ct - padding))
{
x += padding;
ct++;
}
r[i] = rgb[x];
g[i] = rgb[x + 1];
b[i] = rgb[x + 2]; i++;
}
bmp.UnlockBits(bmpData);
return new[] { r, g, b };
}
private static Bitmap AutoCrop(Bitmap bmp)
{
//Get an array containing the R,G,B components of each pixel
var pixels = GetRgb(bmp);
var h = bmp.Height - 1;
var w = bmp.Width;
var top = 0;
var bottom = h;
var left = bmp.Width;
var right = 0;
var white = 0;
const int tolerance = 95;
var prevColor = false;
for (var i = 0; i < pixels[0].Length; i++)
{
int x = (i % (w)), y = (int)(Math.Floor((decimal)(i / w)));
const int tol = 255 * tolerance / 100;
if (pixels[0][i] >= tol && pixels[1][i] >= tol && pixels[2][i] >= tol)
{
white++;
right = (x > right && white == 1) ? x : right;
}
else
{
left = (x < left && white >= 1) ? x : left;
right = (x == w - 1 && white == 0) ? w - 1 : right;
white = 0;
}
if (white == w)
{
top = (y - top < 3) ? y : top;
bottom = (prevColor && x == w - 1 && y > top + 1) ? y : bottom;
}
left = (x == 0 && white == 0) ? 0 : left;
bottom = (y == h && x == w - 1 && white != w && prevColor) ? h + 1 : bottom;
if (x == w - 1)
{
prevColor = (white < w);
white = 0;
}
}
right = (right == 0) ? w : right;
left = (left == w) ? 0 : left;
//Crop the image
if (bottom - top > 0)
{
return bmp.Clone(new Rectangle(left, top, right - left + 1, bottom - top), bmp.PixelFormat);
}
return bmp;
}
}
答案 1 :(得分:0)
您可能想看看Puppeteer(https://pptr.dev/),它使您可以从服务器以编程方式访问浏览器功能。我还可以强烈推荐无浏览器(https://www.browserless.io/),它基于Puppeteer提供了更多功能。
两者都是开源的,Browserless.io也提供了托管选项。 /screenshot
API端点可能是您要寻找的:https://docs.browserless.io/docs/screenshot.html。它以URL作为输入并返回页面图像。
如果您拥有HTML但没有指向网站的URL,则还可以在URL参数中传递编码为base64的HTML内容,例如:
data:text/html;charset=UTF-8;base64,dGVzdAo=