在酷家乐里,当你编辑完之后可以点击渲染进入全景浏览:

就会进入看效果的视角:

不再是编辑视角。
我们也来实现下这个全景浏览功能。
首先加一个渲染按钮:

<div className="btns">
<Button type="primary"><CameraOutlined />渲染</Button>
</div>
加下样式:

display:flex;
justify-content: space-between;
.btns {
margin-right: 20px;
margin-top: 15px;
}

点击按钮的时候,要弹出一个单独的界面来预览:

我们写个新组件:
创建 src/components/Preview/index.tsx
import { CloseCircleOutlined } from "@ant-design/icons";
function Preview() {
return <div id="preview">
<div className='close-btn'>
<CloseCircleOutlined />
</div>
</div>
}
export default Preview;
加一下样式:

#preview {
position: absolute;
background: pink;
width: 100%;
height: 100%;
z-index: 10;
.close-btn {
position: absolute;
right: 20px;
top: 20px;
font-size: 30px;
cursor:pointer;
}
}
引入下:


然后我们要在这里渲染一遍 3D 场景。
首先初始化一下:

useEffect(() => {
const dom = document.getElementById('preview-container')!;
const { } = initPreviewScene(dom);
return () => {
dom.innerHTML = '';
}
}, []);
<div id="preview-container"></div>
加一个 dom,在这下面挂载 canvas
创建 Preview/init-preview.ts
import * as THREE from 'three';
import {
OrbitControls
} from 'three/addons/controls/OrbitControls.js';
export function initPreviewScene(
dom: HTMLElement
) {
const scene = new THREE.Scene();
const axesHelper = new THREE.AxesHelper(5000);
scene.add(axesHelper);
const directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(0, 1500, 0);
scene.add(directionalLight);
const ambientLight = new THREE.AmbientLight(0xffffff, 2.5);
scene.add(ambientLight);
const width = window.innerWidth;
const height = window.innerHeight;
const camera = new THREE.PerspectiveCamera(60, width / height, 1, 100000);
camera.position.set(6000, 4000, 6000);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(width, height);
const controls = new OrbitControls(camera, renderer.domElement);
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
dom.append(renderer.domElement);
window.onresize = function () {
const width = window.innerWidth;
const height = window.innerHeight;
renderer.setSize(width,height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
};
return {
scene,
camera,
controls
}
}
跑一下:

先不着急渲染这个场景,我们先把点击渲染按钮展示这个场景,以及点击关闭按钮关闭的逻辑写一下:
改下关闭按钮的颜色:


点预览按钮显示这个预览的场景:

点击关闭按钮隐藏。
明显需要跨组件通信,我们把它放到 store 里。

showPreview: boolean
toggleShowPreview(): void;
showPreview: false,
toggleShowPreview() {
set(state => {
return {
...state,
showPreview: !state.showPreview
}
})
},
加一个 showPreview 的布尔值和修改它的方法。
然后我们用这个来控制预览界面的显示隐藏:

const { showPreview, toggleShowPreview } = useHouseStore();
style={{display: showPreview ? 'block' : 'none'}}
onClick={toggleShowPreview}
点击关闭的时候切换显示隐藏。
点击渲染按钮的时候也是:

const { toggleShowPreview } = useHouseStore();
onClick={() => toggleShowPreview()}
试下效果:

这样,预览场景的初始化就完成了。
案例代码上传了小册仓库
总结
这节我们加了一下预览场景,它是用来看编辑后的效果的。
我们单独加了一个 Preview 组件和对应的场景初始化代码,点击渲染按钮的时候展示这个场景,点击关闭按钮隐藏。
下节我们来实现预览场景里的内容。