Skip to content

80. 3D 场景保存为图片、视频

Published:

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

2025-06-07 10.17.30.gif

2025-06-07 10.17.55.gif

如果定制好衣服之后,想把它的效果保存下来呢?

这时候就需要把 canvas 保存为图片和视频了。

那 canvas 如何转成图片、视频呢?

浏览器自带了相关 api,就是 canvas.toBlob 和 MediaRecorder

我们直接在上节的代码上改。

加两个按钮:

image.png

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

image.png

然后点击保存图片的时候,就是调用 canvas.toBlob 生成 blob,然后把 blob 作为文件下载。

我们在 3d-init.js 暴露个方法:

image.png

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 接收:

image.png

const downloadImgRef = useRef();
downloadImgRef.current = downloadImg;

点击的时候调用下:

image.png

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

试下效果:

2025-07-08 17.51.04.gif

然后来做保存为视频。

这个用 MediaRecorder 的 api

image.png

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);
}

组件里接收下:

image.png

const downloadVideoRef = useRef();
downloadVideoRef.current = downloadVideo;

然后点击按钮的时候调用:

image.png

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

试一下:

2025-07-08 18.01.59.gif

点击保存为视频按钮后,把衣服转一圈,3 秒后会生成一个视频。

打开可以看到你转一圈这个操作:

2025-07-08 18.03.50.gif

但肯定不能每次点保存视频都手动转一圈,而是要自动转。

我们改下代码:

安装 gsap 来做缓动动画:

pnpm install --save gsap

image.png

gsap.to(scene.rotation, {
    y: Math.PI * 2,
    duration: 3,
    onComplete() {
        scene.rotation.y = 0;
        recorder.stop();
    }
});

就是让场景绕 y 轴转一圈,转完之后停止录制。

这里要转弯之后把 scene.rotation.y 设置为 0,这样下次才能再转。

试一下:

2025-07-08 18.22.14.gif

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

打开视频看一下:

2025-07-08 18.23.20.gif

就是转一圈的视频。

这样就可以 360 度的观察设计好的 T 恤了。

总结

这节我们实现了保存 canvas 为图片、视频的功能。

当我们设计好 T 恤之后,希望把设计保存下来,这时候就希望能生成图片、视频。

我们用 canvas.toBlob 就可以把 canvas 转为 blob,然后用 URL.createObjectURL 把 blob 作为 a 标签的 src,触发下载。

视频用 MediaRecorder 录制,用 gsap 缓动动画把衣服转一圈,把这个过程录制成 webm 的视频。

当有这类需求的时候,就可以把 3D 场景通过图片、视频保存下来。

评论