前面我们实现了 T 恤定制:


如果定制好衣服之后,想把它的效果保存下来呢?
这时候就需要把 canvas 保存为图片和视频了。
那 canvas 如何转成图片、视频呢?
浏览器自带了相关 api,就是 canvas.toBlob 和 MediaRecorder
我们直接在上节的代码上改。
加两个按钮:

<div className='ope-item'>
<Button type='primary'>保存为图片</Button>
<Button type='default'>保存为视频</Button>
</div>

然后点击保存图片的时候,就是调用 canvas.toBlob 生成 blob,然后把 blob 作为文件下载。
我们在 3d-init.js 暴露个方法:

function downloadBlob(blob, filename) {
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
function downloadImg() {
renderer.render(scene, camera);
renderer.domElement.toBlob((blob) => {
if (blob) {
downloadBlob(blob, 'design.png');
}
}, "image/png");
}
调用 canvas.toBlob 方法生成 blob,类型为 image/png
然后用它作为 object url 设置到 a 链接的 src,设置 download 属性,然后触发点击事件来下载。
注意之前要 renderer.render 渲染一次。
之后在组件里用 ref 接收:

const downloadImgRef = useRef();
downloadImgRef.current = downloadImg;
点击的时候调用下:

<Button type='primary' onClick={() => downloadImgRef.current()}>保存为图片</Button>
试下效果:

然后来做保存为视频。
这个用 MediaRecorder 的 api

function downloadVideo() {
const stream = renderer.domElement.captureStream(60);
const recorder = new MediaRecorder(stream);
recorder.start();
recorder.ondataavailable = (event) => {
if (event.data.size > 0) {
downloadBlob(event.data, `design.webm`);
}
};
setTimeout(() => {
recorder.stop();
}, 3000);
}
组件里接收下:

const downloadVideoRef = useRef();
downloadVideoRef.current = downloadVideo;
然后点击按钮的时候调用:

<Button type='default' onClick={() => downloadVideoRef.current()}>保存为视频</Button>
试一下:

点击保存为视频按钮后,把衣服转一圈,3 秒后会生成一个视频。
打开可以看到你转一圈这个操作:

但肯定不能每次点保存视频都手动转一圈,而是要自动转。
我们改下代码:
安装 gsap 来做缓动动画:
pnpm install --save gsap

gsap.to(scene.rotation, {
y: Math.PI * 2,
duration: 3,
onComplete() {
scene.rotation.y = 0;
recorder.stop();
}
});
就是让场景绕 y 轴转一圈,转完之后停止录制。
这里要转弯之后把 scene.rotation.y 设置为 0,这样下次才能再转。
试一下:

现在,点击保存为视频之后,会转一圈,然后生成一个视频。
打开视频看一下:

就是转一圈的视频。
这样就可以 360 度的观察设计好的 T 恤了。
总结
这节我们实现了保存 canvas 为图片、视频的功能。
当我们设计好 T 恤之后,希望把设计保存下来,这时候就希望能生成图片、视频。
我们用 canvas.toBlob 就可以把 canvas 转为 blob,然后用 URL.createObjectURL 把 blob 作为 a 标签的 src,触发下载。
视频用 MediaRecorder 录制,用 gsap 缓动动画把衣服转一圈,把这个过程录制成 webm 的视频。
当有这类需求的时候,就可以把 3D 场景通过图片、视频保存下来。