I am using xBim Toolkit (http://docs.xbim.net/) for 3D object rendering and there was a requirement to create a screenshot of the current scene on button click. xBim is using canvas for graphical representation of the object. The entire project is based on C#, .NET tools and Javascript, so this is the range of the tools that can be used for solving this.
I have already tried by using html2canvas (https://html2canvas.hertzen.com/) and dom-to-image (https://github.com/tsayen/dom-to-image) libraries, but also tried with default canvas methods (like myCanvas.toDataUrl() or myCanvas.toBlob()). All of them produce just an empty image with black or white background, but no xBim object is saved.
The only way I can get any useful screenshot is by using System.Drawing.Graphics and then creating a screenshot of the whole screen (which is not the best implementation for many reasons).
public static void MakeScreenshot()
{
var x = Math.Abs(WebBrowser.MousePosition.X);
var y = Math.Abs(WebBrowser.MousePosition.Y);
var bounds = Screen.FromPoint(new Point(x, y)).Bounds;
Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height);
Graphics graphics = Graphics.FromImage(bitmap as System.Drawing.Image);
graphics.CopyFromScreen(25, 25, 25, 25, bitmap.Size);
string screenshotFilePath = Path.Combine(DirectoryPath, "Screenshot.jpg");
bitmap.Save(screenshotFilePath, ImageFormat.Jpeg);
}
I would like to have screenshot of only canvas area. It is not important if its implemented by using Javascript or C# code (even with System.Drawing.Graphics, but to cut only part of the screen)
If you are using xBim Toolkit as described in question, you need to know that internally it using WebGL for object representation. In order to take a screenshot when WebGl is running, I found out one way(not sure if it is the best one, but it works). You can execute the following Javascript code before loading your page and xBim Viewer:
HTMLCanvasElement.prototype.getContext = function (origFn) {
return function (type, attributes) {
if (type === 'webgl') {
attributes = Object.assign({}, attributes, {
preserveDrawingBuffer: true,
});
}
return origFn.call(this, type, attributes);
};
}(HTMLCanvasElement.prototype.getContext);
It should preserve drawing buffer and enable you to get a screenshot in some of the known ways e.g. using dom-to-image library:
domtoimage.toJpeg(document.getElementById('canvas'), { quality: 0.95 })
.then(function (dataUrl) {
var link = document.createElement('a');
link.download = 'Screenshot.jpeg';
link.href = dataUrl;
link.click();
});