PointerLockControls
Video Lecture
Your browser does not support the video tag.
Description
The PointerLockControls implements the browsers inbuilt Pointer Lock API.
It provides input methods based on the movement of the mouse over time (i.e., deltas), not just the absolute position of the mouse cursor in the viewport. It gives you access to raw mouse movement, locks the target of mouse events to a single element, eliminates limits on how far mouse movement can go in a single direction, and removes the cursor from view. It is ideal for first person 3D games, for example.
Start Scripts
./dist/client/index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 <!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "utf-8" />
< meta name = "viewport" content = "width=device-width, initial-scale=1" />
< title > Three.js TypeScript Tutorials by Sean Bradley : https://sbcode.net/threejs</ title >
< style >
body {
overflow : hidden ;
margin : 0 px ;
}
# menuPanel {
position : absolute ;
background-color : rgba ( 255 , 255 , 255 , 0.5 );
top : 0 px ;
left : 0 px ;
width : 100 % ;
height : 100 % ;
}
# startButton {
height : 50 px ;
width : 200 px ;
margin : -25 px -100 px ;
position : relative ;
top : 50 % ;
left : 50 % ;
font-size : 32 px ;
}
</ style >
</ head >
< body >
< div id = "menuPanel" >
< button id = "startButton" > Click to Start</ button >
</ div >
< script type = "module" src = "bundle.js" ></ script >
</ body >
</ html >
./src/client/client.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 import * as THREE from 'three'
import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls'
import Stats from 'three/examples/jsm/libs/stats.module'
const scene = new THREE . Scene ()
scene . add ( new THREE . AxesHelper ( 5 ))
const camera = new THREE . PerspectiveCamera ( 75 , window . innerWidth / window . innerHeight , 0.1 , 1000 )
camera . position . y = 1
camera . position . z = 2
const renderer = new THREE . WebGLRenderer ()
renderer . setSize ( window . innerWidth , window . innerHeight )
document . body . appendChild ( renderer . domElement )
const menuPanel = document . getElementById ( 'menuPanel' ) as HTMLDivElement
// const startButton = document.getElementById('startButton') as HTMLInputElement
// startButton.addEventListener(
// 'click',
// function () {
// controls.lock()
// },
// false
// )
const controls = new PointerLockControls ( camera , renderer . domElement )
// controls.addEventListener('change', () => console.log("Controls Change"))
// controls.addEventListener('lock', () => menuPanel.style.display = 'none')
// controls.addEventListener('unlock', () => menuPanel.style.display = 'block')
const planeGeometry = new THREE . PlaneGeometry ( 100 , 100 , 50 , 50 )
const material = new THREE . MeshBasicMaterial ({
color : 0x00ff00 ,
wireframe : true ,
})
const plane = new THREE . Mesh ( planeGeometry , material )
plane . rotateX ( - Math . PI / 2 )
scene . add ( plane )
const cubes : THREE.Mesh [] = []
for ( let i = 0 ; i < 100 ; i ++ ) {
const geo = new THREE . BoxGeometry ( Math . random () * 4 , Math . random () * 16 , Math . random () * 4 )
const mat = new THREE . MeshBasicMaterial ({ wireframe : true })
switch ( i % 3 ) {
case 0 :
mat.color = new THREE . Color ( 0xff0000 )
break
case 1 :
mat.color = new THREE . Color ( 0xffff00 )
break
case 2 :
mat.color = new THREE . Color ( 0x0000ff )
break
}
const cube = new THREE . Mesh ( geo , mat )
cubes . push ( cube )
}
cubes . forEach (( c ) => {
c . position . x = Math . random () * 100 - 50
c . position . z = Math . random () * 100 - 50
c . geometry . computeBoundingBox ()
c . position . y = (( c . geometry . boundingBox as THREE . Box3 ). max . y - ( c . geometry . boundingBox as THREE . Box3 ). min . y ) / 2
scene . add ( c )
})
// const onKeyDown = function (event: KeyboardEvent) {
// switch (event.code) {
// case "KeyW":
// controls.moveForward(.25)
// break
// case "KeyA":
// controls.moveRight(-.25)
// break
// case "KeyS":
// controls.moveForward(-.25)
// break
// case "KeyD":
// controls.moveRight(.25)
// break
// }
// }
// document.addEventListener('keydown', onKeyDown, false)
window . addEventListener ( 'resize' , onWindowResize , false )
function onWindowResize () {
camera . aspect = window . innerWidth / window . innerHeight
camera . updateProjectionMatrix ()
renderer . setSize ( window . innerWidth , window . innerHeight )
render ()
}
const stats = new Stats ()
document . body . appendChild ( stats . dom )
function animate () {
requestAnimationFrame ( animate )
//controls.update()
render ()
stats . update ()
}
function render () {
renderer . render ( scene , camera )
}
animate ()
Final Script
./src/client/client.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 import * as THREE from 'three'
import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls'
import Stats from 'three/examples/jsm/libs/stats.module'
const scene = new THREE . Scene ()
scene . add ( new THREE . AxesHelper ( 5 ))
const camera = new THREE . PerspectiveCamera ( 75 , window . innerWidth / window . innerHeight , 0.1 , 1000 )
camera . position . y = 1
camera . position . z = 2
const renderer = new THREE . WebGLRenderer ()
renderer . setSize ( window . innerWidth , window . innerHeight )
document . body . appendChild ( renderer . domElement )
const menuPanel = document . getElementById ( 'menuPanel' ) as HTMLDivElement
const startButton = document . getElementById ( 'startButton' ) as HTMLInputElement
startButton . addEventListener (
'click' ,
function () {
controls . lock ()
},
false
)
const controls = new PointerLockControls ( camera , renderer . domElement )
//controls.addEventListener('change', () => console.log("Controls Change"))
controls . addEventListener ( 'lock' , () => ( menuPanel . style . display = 'none' ))
controls . addEventListener ( 'unlock' , () => ( menuPanel . style . display = 'block' ))
const planeGeometry = new THREE . PlaneGeometry ( 100 , 100 , 50 , 50 )
const material = new THREE . MeshBasicMaterial ({
color : 0x00ff00 ,
wireframe : true ,
})
const plane = new THREE . Mesh ( planeGeometry , material )
plane . rotateX ( - Math . PI / 2 )
scene . add ( plane )
const cubes : THREE.Mesh [] = []
for ( let i = 0 ; i < 100 ; i ++ ) {
const geo = new THREE . BoxGeometry ( Math . random () * 4 , Math . random () * 16 , Math . random () * 4 )
const mat = new THREE . MeshBasicMaterial ({ wireframe : true })
switch ( i % 3 ) {
case 0 :
mat.color = new THREE . Color ( 0xff0000 )
break
case 1 :
mat.color = new THREE . Color ( 0xffff00 )
break
case 2 :
mat.color = new THREE . Color ( 0x0000ff )
break
}
const cube = new THREE . Mesh ( geo , mat )
cubes . push ( cube )
}
cubes . forEach (( c ) => {
c . position . x = Math . random () * 100 - 50
c . position . z = Math . random () * 100 - 50
c . geometry . computeBoundingBox ()
c . position . y = (( c . geometry . boundingBox as THREE . Box3 ). max . y - ( c . geometry . boundingBox as THREE . Box3 ). min . y ) / 2
scene . add ( c )
})
const onKeyDown = function ( event : KeyboardEvent ) {
switch ( event . code ) {
case 'KeyW' :
controls . moveForward ( 0.25 )
break
case 'KeyA' :
controls . moveRight ( - 0.25 )
break
case 'KeyS' :
controls . moveForward ( - 0.25 )
break
case 'KeyD' :
controls . moveRight ( 0.25 )
break
}
}
document . addEventListener ( 'keydown' , onKeyDown , false )
window . addEventListener ( 'resize' , onWindowResize , false )
function onWindowResize () {
camera . aspect = window . innerWidth / window . innerHeight
camera . updateProjectionMatrix ()
renderer . setSize ( window . innerWidth , window . innerHeight )
render ()
}
const stats = new Stats ()
document . body . appendChild ( stats . dom )
function animate () {
requestAnimationFrame ( animate )
//controls.update()
render ()
stats . update ()
}
function render () {
renderer . render ( scene , camera )
}
animate ()
Useful Links
PointerLockControls (Official Documentation)
Pointer Lock API
KeyboardEvent.code