threejs之检测拖动模型和停止拖动模型以及鼠标缩放事件
controls.value.addEventListener('start',startEvent)
controls.value.addEventListener('end', endEvent);
这样子给轨道控制器绑定事件后即可。
-
mesh.position.length() : 获得mesh到当前场景中心的距离
-
-
mesh.position.distanceTo(camera.postion): 获得当前mesh到相机的距离,这里参数可以是任意 vector3 坐标
-
-
mesh.position.normalize(): 将mesh到scene 中心的距离规范化为1,此刻打印mesh.position.length() == 1
-
-
mesh.roration.reorder('yxz') : 假如你想要在三个方向上去旋转物体,使用mesh.roration.reorder可以控制物体先在y轴方向上旋转,在x,最后z方向上旋转。****
-
-
camera.lookAt() : 让相机正对某个三维坐标!!!默认scene 中心
-
threejs animation动画中,让动画速率在所有帧率的电脑中,维持一致的两种方法:
method1: 借助于 Date.now()
method2: 借助于threejs内置函数方法 clock()
# [gsap应用之threejs动画效果](https://www.cnblogs.com/Hijacku/p/17265486.html "发布于 2023-03-28 15:45")
import * as THREE from 'three'
import gsap from 'gsap'
// Canvas
const canvas = document.querySelector('canvas.webgl')
// Scene
const scene = new THREE.Scene()
// Object
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
// animation
const animations = () => {
// 这里将mesh的x坐标,进行从0-》2-》0,实现这样子一个简单的动画效果
gsap.to(mesh.position, { duration: 1, delay: 1, x: 2 })
gsap.to(mesh.position, { duration: 1, delay: 2, x: 0 })
}
animations()
// Sizes
const sizes = {
width: 800,
height: 600
}
// Camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
camera.position.z = 3
scene.add(camera)
// Renderer
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
const tick = () => {
renderer.render(scene, camera)
window.requestAnimationFrame(tick)
// 动画一定需要配合帧动画请求!!!
}
tick()
renderer.setSize(sizes.width, sizes.height)
threejs-camera&controls&renderer(WebGLRenderer)
- ArrayCamera: 一般用于,展示益、一个场景存在多个物体,每个物体各自拥有自己的视角的这种场景。
- CubeCamera:一次性创建六个方位的相机(类似于正方体六个面,立方全景图中所有方位)
- StereoCamera: 立体相机,创建于类似于VR场景的,实现相机视角跟随鼠标的效果
- OrthographyCamera: 正交相机,用于创建没有透视场景的渲染效果。不会有近大远小的视觉差等效果?
- PerspectiveCamera: 透视相机, 用于模拟人眼场景的各种场景效果。会有近大远小的视觉差
About PerspectiveCamera:
四个参数:
-
fov: 指的是 垂直方向上的可视角度(vertical vision angle | in degrees),一般建议设置在45-75之前,此值越大,物体看起来越小,(只增大fov,其他条件不变的话)
-
aspect:
-
near:小于 near的物体,不会被相机照到
-
far:大于 near的物体,不会被相机照到(这里的值可以参考,camera.position.length() 得到一个能看到当前视角全部物体的最小的一个far值来设置!!!)
about OrthographyCamera:此相机,就像一片透明玻璃一样去拍照场景中的物体,如下图。
六个参数:
1.left:
2.right:
3.top:
4.bottom:
5.near:
-
6.far:
知识点:在其他场景都不变,只改变PerspectiveCamera 为 OrthographicCamera时, 假如在PerspectiveCamera下显示的是一个立方体,但是可能在OrthographicCamera下,看起来是个长方体了,这是因为可能正交相机左右(left right),或者上下(top bottom)给的值没有乘以 PerspectiveCamera的 aspect ratio.设置后,看起来就是个立方体了。
Controls&Renderer
1 import * as THREE from 'three'
2 import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
3 import gsap from 'gsap'
4 // Canvas
5 const canvas = document.querySelector('canvas.webgl')
6
7 // Scene
8 const scene = new THREE.Scene()
9
10
11 // Object
12 const geometry = new THREE.BoxGeometry(1, 1, 1)
13 const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
14 const mesh = new THREE.Mesh(geometry, material)
15 scene.add(mesh)
16
17 // animation
18 const animations = () => {
19 gsap.to(mesh.position, { duration: 1, delay: 1, x: 2 })
20 gsap.to(mesh.position, { duration: 1, delay: 2, x: 0 })
21 }
22 animations()
23 // Sizes
24 const sizes = {
25 width: window.innerWidth,
26 height: window.innerHeight
27 }
28
29 // Camera
30 const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
31 camera.position.z = 3
32 scene.add(camera)
33
34 // controls
35
36 const controls = new OrbitControls(camera, canvas);
37 controls.enableDamping = true
38 //开启阻尼,也就是惯性, 然后需要在每一帧进行controls.update()
39 //
40 // controls.target.y = 2 //controls target 指向的是对象围绕的焦点
41 // controls.update()
42
43 // Renderer
44 const renderer = new THREE.WebGLRenderer({
45 canvas: canvas
46 })
47 const tick = () => {
48 controls.update()
49 renderer.render(scene, camera)
50 window.requestAnimationFrame(tick)
51 // 动画一定需要配合帧动画请求!!!
52 }
53 tick()
54 let cursor = {
55 x:0,
56 y:0
57 }
58 // 绑定鼠标事件
59 window.addEventListener('mousemove', (event) => {
60 // 这样子会使得x,y 坐标值会归于(-0.5-0.5 这个区间),
61 cursor.x = event.clientX / sizes.width - 0.5
62 cursor.y = -(event.clientY / sizes.height - 0.5)
63 // 不加符号,会使得鼠标上下移动的时候,mesh看起来是跟随鼠标方向的,但是其实移动相机,mesh最终效果是要跟鼠标反向运动(相机向右,以相机为参照物,其实mesh向左)。
64 //camera.position.x = cursor.x
65 //camera.position.y = cursor.y
66
67 // 让相机围绕着mesh 旋转(首先要清楚 这里实现旋转,改变位置的话,是 x和z方向旋转)
68 // camera.position.x = Math.sin(cursor.x * Math.PI * 2) * 3
69 // camera.position.z = Math.cos(cursor.x * Math.PI * 2) * 3
70 // camera.position.y = cursor.y * 6
71 // camera.lookAt(mesh.position)
72 })
73
74 //window resize handle
75 window.addEventListener('resize', () => {
76 sizes.width = window.innerWidth
77 sizes.height = window.innerHeight
78
79 camera.aspect = sizes.width / sizes.height
80 camera.updateProjectionMatrix()
81 //修改相机参数后,需要统计threejs 去更改 projectMatrix, 项目矩阵?
82
83 //renderer 修改画布的size
84 renderer.setSize(sizes.width, sizes.height)
85 renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
86 })
87
88 // 绑定全屏事件
89 window.addEventListener('dblclick', () => {
90 // 注意,这个特性,对于 safari 浏览器无效
91 // if(!document.fullscreenElement) {
92 // canvas.requestFullscreen()
93 // }else {
94 // document.exitFullscreen()
95 // }
96
97 //最终兼容写法
98 const fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement
99 if(!fullscreenElement) {
100 if(canvas.requestFullscreen) {
101 canvas.requestFullscreen()
102 }else if(canvas.webkitRequestFullscreen) {
103 canvas.webkitRequestFullscreen()
104 }
105 }else {
106 if(document.exitFullscreen) {
107 document.exitFullscreen()
108 }else if(document.webkitExitFullscreen) {
109 document.webkitExitFullscreen()
110 }
111 }
112 })
113
114 renderer.setSize(sizes.width, sizes.height)
115 // 规定渲染器,设定像素比 为1 or 2 有益于性能!!!
116 renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))