Three.js:如何设置自定义分辨率并导出指定尺寸PNG图片?
解决Three.js WebGLRenderer导出自定义分辨率PNG的问题
嘿,我刚好碰到过类似的问题,这就来帮你搞定这个自定义分辨率导出的bug!
你遇到的核心问题是:直接修改尺寸后没有让渲染器用新分辨率重新渲染场景,而且可能没同步更新相机参数,导致导出的还是原来画布的尺寸内容。下面是完整的解决思路和修改后的代码:
关键解决步骤
- 保存原始渲染状态:导出前先记录当前渲染器的尺寸、像素比,还有相机的宽高比,导出后要恢复回来,不然页面上的3D视图会变形。
- 映射自定义分辨率:把你选择的尺寸选项(比如's'/'m'/'l')对应到具体的宽高数值。
- 更新渲染器参数:设置新的像素尺寸,注意不要修改canvas的CSS样式(避免页面元素乱跑),同时调整像素比保证导出图片清晰。
- 同步相机参数:更新相机的宽高比并重新计算投影矩阵,防止场景拉伸变形。
- 重新渲染场景:这是最关键的一步!必须让渲染器用新尺寸重新绘制一次场景,才能得到对应分辨率的图像。
- 导出并恢复原始状态:导出图片后,把渲染器和相机恢复到原来的设置,保证页面正常显示。
修改后的完整代码示例
// 假设你已经定义了scene和camera变量 var width, height, renderer3D, scene, camera; renderer3D = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true }); this.ExportImage = function(){ var imgSize = document.getElementById('imageSizeOption').value; // 定义尺寸选项对应的具体宽高(你可以根据需求修改) const sizeMapping = { 's': { width: 800, height: 600 }, 'm': { width: 1200, height: 900 }, 'l': { width: 1920, height: 1080 }, 'xl': { width: 2560, height: 1440 } }; // 获取目标尺寸,默认用当前画布尺寸 const targetSize = sizeMapping[imgSize] || { width: renderer3D.domElement.width, height: renderer3D.domElement.height }; // 保存原始渲染参数,用于后续恢复 const originalWidth = renderer3D.domElement.width; const originalHeight = renderer3D.domElement.height; const originalPixelRatio = renderer3D.getPixelRatio(); const originalCameraAspect = camera.aspect; try { // 设置渲染器的新像素尺寸(第三个参数false:不修改canvas的CSS样式) renderer3D.setSize(targetSize.width, targetSize.height, false); // 设置像素比,用设备像素比保证导出图片清晰,也可以自定义比如2 renderer3D.setPixelRatio(window.devicePixelRatio); // 更新相机宽高比并重新计算投影矩阵 camera.aspect = targetSize.width / targetSize.height; camera.updateProjectionMatrix(); // 关键!用新尺寸重新渲染场景 renderer3D.render(scene, camera); // 导出PNG图片 const dataURL = renderer3D.domElement.toDataURL('image/png'); // 创建下载链接并触发下载 const downloadLink = document.createElement('a'); downloadLink.download = `threejs-export-${imgSize}.png`; downloadLink.href = dataURL; downloadLink.click(); } finally { // 恢复原始渲染参数,保证页面上的3D视图正常显示 renderer3D.setSize(originalWidth, originalHeight, false); renderer3D.setPixelRatio(originalPixelRatio); camera.aspect = originalCameraAspect; camera.updateProjectionMatrix(); renderer3D.render(scene, camera); } };
重点注意事项
- 必须重新渲染:如果跳过
renderer3D.render(scene, camera)这一步,导出的还是修改尺寸前的画布内容,分辨率自然不会变。 - 相机参数同步:相机的宽高比必须和渲染器尺寸匹配,否则导出的图片会出现拉伸或压缩的情况。
- 恢复原始状态:一定要在finally块里恢复原始设置,不然导出后页面上的3D视图会变成导出的尺寸,影响用户体验。
内容的提问来源于stack exchange,提问作者karthick187
相关产品推荐
相关产品推荐

