Autodesk Forge Viewer getScreenshot方法截图宽高比控制问题求助
问题:Autodesk Forge Viewer getScreenshot 无法按指定宽高比生成截图
问题描述:
我尝试用Autodesk Forge Viewer的getScreenshot方法,指定明确的宽高来生成截图,当前代码是:
this.viewer.getScreenShot( this.width, this.height, img => this.createPDF(img));
当我把高度设为画布完整高度时,能计算对应宽度适配1:2这类比例;但想要计算高度匹配16:9比例时,不管设置的this.height是多少,截图都会用画布的完整高度,宽度自动调整成16:9。我不确定是操作有误、漏了设置,还是这是Viewer的固有特性,导致没法基于当前画布生成16:9的截图。目前我已经能基于比例和clientToWorld坐标渲染出对应帧,但截图始终会扩展为完整画布高度,求解决方案。
解决方案:
首先得明确:这其实是Forge Viewer getScreenshot方法的固有特性——它会优先保证场景内容的原始比例不被拉伸,所以当你传入的宽高比例和当前Viewer视口比例不一致时,它会自动调整你传入的参数,优先匹配场景的原始比例,这就导致了你遇到的问题。下面提供两种可行的解决思路:
1. 手动裁剪截图(推荐,不影响用户界面)
既然getScreenshot返回的是完整画布的图像,我们可以手动创建一个canvas,按照目标比例裁剪出需要的区域,再把裁剪后的图像传入你的createPDF方法。示例代码如下:
this.viewer.getScreenShot(this.viewer.container.clientWidth, this.viewer.container.clientHeight, (img) => { // 定义目标宽高比,比如16:9 const targetRatio = 16 / 9; let cropWidth, cropHeight, startX, startY; // 计算裁剪区域(以图像中心为基准,保证内容居中) if (img.width / img.height > targetRatio) { // 原图宽高比大于目标比例,裁剪左右两侧 cropHeight = img.height; cropWidth = cropHeight * targetRatio; startX = (img.width - cropWidth) / 2; startY = 0; } else { // 原图宽高比小于目标比例,裁剪上下两侧 cropWidth = img.width; cropHeight = cropWidth / targetRatio; startY = (img.height - cropHeight) / 2; startX = 0; } // 创建用于裁剪的canvas const cropCanvas = document.createElement('canvas'); cropCanvas.width = cropWidth; cropCanvas.height = cropHeight; const ctx = cropCanvas.getContext('2d'); // 绘制裁剪区域到新canvas ctx.drawImage(img, startX, startY, cropWidth, cropHeight, 0, 0, cropWidth, cropHeight); // 将裁剪后的canvas转为图像,传入createPDF const croppedImg = new Image(); croppedImg.src = cropCanvas.toDataURL('image/png'); croppedImg.onload = () => { this.createPDF(croppedImg); }; });
2. 临时调整Viewer视口(适合需要精确渲染比例的场景)
如果你希望截图就是Viewer渲染时的精确比例(而非事后裁剪),可以临时修改Viewer容器的宽高为目标比例,刷新渲染后再截图,最后恢复容器原始尺寸:
// 保存容器原始尺寸 const originalWidth = this.viewer.container.clientWidth; const originalHeight = this.viewer.container.clientHeight; // 目标宽高比16:9,这里以原始宽度为基准计算对应高度 const targetHeight = originalWidth / (16/9); // 修改容器样式为目标尺寸 this.viewer.container.style.width = `${originalWidth}px`; this.viewer.container.style.height = `${targetHeight}px`; // 刷新Viewer渲染,让场景适配新的视口 this.viewer.resize(); // 延迟截图,确保Viewer完成渲染(时间可根据实际情况调整) setTimeout(() => { this.viewer.getScreenShot(originalWidth, targetHeight, (img) => { this.createPDF(img); // 恢复容器原始尺寸并刷新 this.viewer.container.style.width = `${originalWidth}px`; this.viewer.container.style.height = `${originalHeight}px`; this.viewer.resize(); }); }, 500);
注意事项:
- 临时调整视口的方法需要给Viewer足够的渲染时间,建议用
viewer.waitForLoadDone()替代setTimeout,能更精准地捕获渲染完成的时机。 - 手动裁剪的方法不会改变用户看到的界面,更适合大多数场景;而临时调整视口的方法会让界面短暂变化,需要根据你的需求选择。
内容的提问来源于stack exchange,提问作者JuliTrusalin
相关产品推荐
相关产品推荐

