赞
踩
在Three中提供2D和3Dcss渲染器供用户使用,如果你希望将二维或三维物体和基于HTML的标签相结合,则这一渲染器将十分有用。在这里,各个DOM元素也被包含到一个CSS2DObject或CSS3DObject实例中,并被添加到场景图中。
目录
CSS2DRenderer是CSS3DRenderer(CSS 3D渲染器)的简化版本,唯一支持的变换是位移。
如果你希望将三维物体和基于HTML的标签相结合,则这一渲染器将十分有用。在这里,各个DOM元素也被包含到一个CSS2DObject实例中,并被添加到场景图中。
例如官方他提供的标签案例(label):
通过HTML及CSS设置标签样式,并绑定至Three创建的物体中:
同理还有molecules分子案例:
返回一个包含有渲染器宽和高的对象。
使用camera渲染scene。
将渲染器的尺寸调整为(width, height).
CSS3DRenderer用于通过CSS3的transform属性, 将层级的3D变换应用到DOM元素上。 如果你希望不借助基于canvas的渲染来在你的网站上应用3D变换,那么这一渲染器十分有趣。 同时,它也可以将DOM元素与WebGL的内容相结合。
然而,这一渲染器也有一些十分重要的限制:
因此,CSS3DRenderer仅仅关注普通的DOM元素,这些元素被包含到了特殊的对象中(CSS3DObject或者CSS3DSprite),然后被加入到场景图中。
例如Three官方提供的元素周期表案例:
返回一个包含有渲染器宽和高的对象。
使用perspective camera渲染scene。
将渲染器尺寸重新调整为(width, height)。
通过使用二维css渲染器实现官方地月围绕旋转及label标签的显示:
实现原理:
1)导入CSS2DRenderer, CSS2DObject;
2)添加提示标签;
3)实例化标签为CSS2DObject;
4)设置标签Object的位置;
5)将标签添加至物体中;
6)实例化css2d渲染器。
main.js:
- import * as THREE from "three";
- import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
- import {
- CSS2DRenderer,
- CSS2DObject,
- } from "three/examples/jsm/renderers/CSS2DRenderer.js";
-
- let camera, scene, renderer, labelRenderer;
-
- const clock = new THREE.Clock();
- const textureLoader = new THREE.TextureLoader();
-
- let moon;
- let chinaLabel;
- const raycaster = new THREE.Raycaster();
- init();
- animate();
-
-
- // 创建射线
-
- function init() {
- const EARTH_RADIUS = 1;
- const MOON_RADIUS = 0.27;
-
- camera = new THREE.PerspectiveCamera(
- 45,
- window.innerWidth / window.innerHeight,
- 0.1,
- 200
- );
- camera.position.set(0, 5, -10);
-
- scene = new THREE.Scene();
- // 设置直线光源
- const dirLight = new THREE.DirectionalLight(0xffffff);
- dirLight.position.set(0, 0, 1);
- scene.add(dirLight);
- const light = new THREE.AmbientLight(0xffffff, 0.5); // soft white light
- scene.add(light);
-
- // 设置地球实体
- const earthGeometry = new THREE.SphereGeometry(EARTH_RADIUS, 16, 16);
- const earthMaterial = new THREE.MeshPhongMaterial({
- specular: 0x333333,
- shininess: 5,
- map: textureLoader.load("textures/planets/earth_atmos_2048.jpg"),
- specularMap: textureLoader.load("textures/planets/earth_specular_2048.jpg"),
- normalMap: textureLoader.load("textures/planets/earth_normal_2048.jpg"),
- normalScale: new THREE.Vector2(0.85, 0.85),
- });
-
- const earth = new THREE.Mesh(earthGeometry, earthMaterial);
- // earth.rotation.y = Math.PI;
- scene.add(earth);
- //设置月球实体
- const moonGeometry = new THREE.SphereGeometry(MOON_RADIUS, 16, 16);
- const moonMaterial = new THREE.MeshPhongMaterial({
- shininess: 5,
- map: textureLoader.load("textures/planets/moon_1024.jpg"),
- });
- moon = new THREE.Mesh(moonGeometry, moonMaterial);
- scene.add(moon);
-
- // 添加提示标签
- const earthDiv = document.createElement('div');
- earthDiv.className = "label";
- earthDiv.innerHTML = "地球";
- const earthLabel = new CSS2DObject(earthDiv);
- earthLabel.position.set(0,1,0);//相对于父级元素的位置
- earth.add(earthLabel);
-
- // 中国
- const chinaDiv = document.createElement('div');
- chinaDiv.className = "label1";
- chinaDiv.innerHTML = "中国";
- chinaLabel = new CSS2DObject(chinaDiv);
- chinaLabel.position.set(-0.3,0.5,-0.9);
- earth.add(chinaLabel);
- console.log(chinaLabel)
- // 月球
- const moonDiv = document.createElement('div');
- moonDiv.className = "label";
- moonDiv.innerHTML = "月球";
- const moonLabel = new CSS2DObject(moonDiv);
- moonLabel.position.set(0,0.3,0);
- moon.add(moonLabel);
-
-
- // 实例化css2d的渲染器
- labelRenderer = new CSS2DRenderer();
- labelRenderer.setSize(window.innerWidth, window.innerHeight);
- document.body.appendChild(labelRenderer.domElement)
- //设置样式
- labelRenderer.domElement.style.position = 'fixed';
- labelRenderer.domElement.style.top = '0px';
- labelRenderer.domElement.style.left = '0px';
- labelRenderer.domElement.style.zIndex = '10';//设置层级
-
-
-
-
- renderer = new THREE.WebGLRenderer();
- renderer.setPixelRatio(window.devicePixelRatio);
- renderer.setSize(window.innerWidth, window.innerHeight);
- document.body.appendChild(renderer.domElement);
-
-
-
- const controls = new OrbitControls(camera, labelRenderer.domElement);
- controls.minDistance = 5;
- controls.maxDistance = 100;
-
- //
-
- window.addEventListener("resize", onWindowResize);
- }
-
- function onWindowResize() {
- camera.aspect = window.innerWidth / window.innerHeight;
-
- camera.updateProjectionMatrix();
-
- renderer.setSize(window.innerWidth, window.innerHeight);
- labelRenderer.setSize(window.innerWidth, window.innerHeight);
- }
- function animate() {
- requestAnimationFrame(animate);
-
- const elapsed = clock.getElapsedTime();
-
- moon.position.set(Math.sin(elapsed) * 5, 0, Math.cos(elapsed) * 5);
-
- // 通过射线设置标签隐藏
- const chinaPosition = chinaLabel.position.clone();
- // 计算出标签跟摄像机的距离
- const labelDistance = chinaPosition.distanceTo(camera.position);
- // 检测射线的碰撞
- // chinaLabel.position
- // 向量(坐标)从世界空间投影到相机的标准化设备坐标 (NDC) 空间。
- chinaPosition.project(camera);
- raycaster.setFromCamera(chinaPosition,camera);
-
- const intersects = raycaster.intersectObjects(scene.children,true)
- // console.log(intersects)
-
- // 如果没有碰撞到任何物体,那么让标签显示
- if(intersects.length == 0){
- chinaLabel.element.classList.add('visible');
-
- }else{
- // if(labelDistance)
- const minDistance = intersects[0].distance;
- console.log(minDistance,labelDistance)
- if(minDistance<labelDistance){
- chinaLabel.element.classList.remove('visible');
- }else{
- chinaLabel.element.classList.add('visible');
- }
-
- }
-
-
- // 标签渲染器渲染
- labelRenderer.render(scene,camera);
-
- renderer.render(scene, camera);
- }
实现效果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。