背景
最近在做一个任务,就是二维页面里嵌入展示三维模型的组件。完成以后,发现当缩小或放大浏览器窗口时,虽然模型大致还在屏幕中间,但是通过开发者工具可以看到:其所在的canvas的大小比canvas所在的div的大小要大了十几到几十px。所幸应该是大的不多,所以模型大致仍能看到是在屏幕中间。但是这个问题还是需要解决一下。
原因
经过半天的排查,我发现非常奇怪的一点是,明明监听窗口大小变化的代码如下所示:
onWindowResize(): void {
if (!isNullOrUndefined(this.camera)) {
// @ts-ignore
this.camera.aspect = this.rendererCanvas.offsetWidth / this.rendererCanvas.offsetHeight;
this.camera?.updateProjectionMatrix();
this.renderer?.setPixelRatio(window.devicePixelRatio);
this.renderer?.setSize(this.rendererCanvas.offsetWidth, this.rendererCanvas.offsetHeight);
}
其中this.rendererCanvas就是显示三维模型的canvas的div。在开发者工具里看该div的宽和高明明和其父元素的宽高是一致的,但是canvas的宽高始终比该div要大一点点,但是代码里this.renderer的大小是和div的大小是一致的。
最后我打印了每一帧canvas的大小和div的大小,发现当缩小或放大浏览器窗口的时候,div的大小会变化至一个略大于实际大小的值,此时该值被赋给了this.renderer,也就造成了canvas的大小和实际大小不一致,但是过了约20帧以后,div的宽高会从那个略大的值恢复到实际值,也就造成了我每次在开发者工具里看div的大小都是对的。
至于为什么会有这种宽高的抖动,我也没查到,主要是也不知道该咋查,有知道的大佬不妨提示一下。
解决
我能想到的解决方法就是延时了,把那20多帧熬过去之后,再将稳定下来的实际值赋给canvas:
setTimeOut(() => {
this.renderer?.setSize(this.rendererCanvas.offsetWidth, this.rendererCanvas.offsetHeight);
}, 300);