threejs扩展控件 OrbitControls.js
可以使用鼠标对场景进行操作,比如旋转场景,移动场景,对场景进行缩放;
var controls = new THREE.OrbitControls(camera, renderer.domElement);
复制代码
定义一个轨道控制器,要想使轨道控制器生效,必须循环渲染场景
requestAnimationFrame
var controls = new THREE.OrbitControls(camera, renderer.domElement);
// 渲染函数
function render() {
controls.update()
renderer.render(scene, camera); //执行渲染操作
requestAnimationFrame(render)
render();
复制代码
控制器提供几个方法
addEventListener
监听方法,接受两个参数
type
、
listener
controls.addEventListener('change', changeControls)
function changeControls(event) {
console.log(camera.position)
复制代码
轨道控制是用来控制相机,使相机进行轨道运动,所以可以在监听的函数中随时查看相机的位置信息
removeEventListener
用来移除监听事件
controls.addEventListener('change', changeControls, false)
function changeControls() {
console.log(event.type)
setTimeout(()=>{
controls.removeEventListener('change', changeControls)
},5000)
复制代码
监听的type除了change,还可以监听开始(star)时,和结束(end)时,具体可以看一下控制器的 源码
var scope = this;
var changeEvent = { type: 'change' };
var startEvent = { type: 'start' };
var endEvent = { type: 'end' };
复制代码
也可以监听controls.document
controls.domElement.addEventListener( 'mousedown', onMouseDown, false );
function onMouseDown(){
console.log(event)
复制代码
其他两个平时没用到,源码中有应用到,是调用reset方法和update方法派发事件,还有待探索
从动图中可以看出,左键旋转和右键移动event.type都是mousemove,缩放event.type是wheel
从打印出的日志可以看出来进行了什么操作,一会限制操作的时候会起到作用 官网提供了很多api,一起来看一看
autoRotate
.autoRotate : Boolean
将其设为true,以自动围绕目标旋转。
请注意,如果它被启用,你必须在你的动画循环里调用.update()。
复制代码
这个api主要是可以自动让场景进行旋转,可以控制旋转速度
.autoRotateSpeed : Float
当 .autoRotate : Boolean为true时,围绕目标旋转的速度将有多快,默认值为2.0,相当于在60fps时每旋转一次需要30秒。
请注意,如果 .autoRotate : Boolean被启用,你必须在你的动画循环里调用.update()。
复制代码
var controls = new THREE.OrbitControls(camera, renderer.domElement);
// console.log(controls)
controls.addEventListener('change', changeControls)
function changeControls(event) {
console.log(event.type)
controls.autoRotate = true // 启用自动旋转
controls.autoRotateSpeed = 10
// 渲染函数
function render() {
renderer.render(scene, camera); //执行渲染操作
controls.update() //更新控制器
requestAnimationFrame(render)
render();
enableDamping
将其设置为true以启用阻尼(惯性),这将给控制器带来重量感。默认值为false。
请注意,如果该值被启用,你将必须在你的动画循环里调用.update()。
dampingFactor
当 .enableDamping : Boolean设置为true的时候,阻尼惯性有多大。
请注意,要使得这一值生效,你必须在你的动画循环里调用.update()。
将其设置为true以启用阻尼(惯性),这将给控制器带来重量感。默认值为false。
请注意,如果该值被启用,你将必须在你的动画循环里调用.update()。
controls.enableDamping = true
controls.dampingFactor = 0.1
略微有一点丝滑的感觉,鼠标旋转到一定角度松开后模型会继续“滑行”一段距离,控制台也是一直在打印
enableKeys
启用或禁用键盘控制。
controls.enableKeys = true // default true
复制代码
keys:
这一对象包含了用于控制相机平移的按键代码的引用。默认值为4个箭头(方向)键。
controls.keys = {
LEFT: 37, //left arrow
UP: 38, // up arrow
RIGHT: 39, // right arrow
BOTTOM: 40 // down arrow
复制代码
keyPanSpeed
当使用键盘按键的时候,相机平移的速度有多快。默认值为每次按下按键时平移7像素。
controls.keyPanSpeed = 7
复制代码
三者代码
controls.addEventListener('change', changeControls)
function changeControls() {
console.log(event.keyCode)
// controls.enableDamping = true
// controls.dampingFactor = 0.1
controls.enableKeys = true
controls.keyPanSpeed = 7
controls.keys = {
LEFT: 37, //left arrow
UP: 38, // up arrow
RIGHT: 39, // right arrow
BOTTOM: 40 // down arrow
有一个现象,在按下左箭头的时候,场景往右移动,本以为是哪里写错了,
反过来一想,轨道控制器是控制相机位置的,所以是相机向左边移动了7像素,场景自然向左边移动了
各种控制器禁用
enabled
控制器是否被启用。
enablePan
启用或禁用摄像机平移,默认为true。
enableRotate
启用或禁用摄像机水平或垂直旋转。默认值为true。
请注意,可以通过将polar angle或者azimuth angle 的min和max设置为相同的值来禁用单个轴, 这将使得水平旋转或垂直旋转固定为所设置的值。
enableZoom
启用或禁用摄像机的缩放。
以上各种禁用 只改一下值就可以生效,不赘述
各种操作的角度限制
maxAzimuthAngle
水平旋转的角度的上限
minAzimuthAngle
水平旋转的角度的下限
minPolarAngle
垂直旋转的角度的下限
maxPolarAngle
垂直旋转的角度的上限
.minZoom
你能够将相机放大多少 ( 仅适用于OrthographicCamera ) ,其默认值为0。
.maxZoom
你能够将相机缩小多少 ( 仅适用于OrthographicCamera only ) ,其默认值为Infinity。
.zoomSpeed
摄像机缩放的速度,其默认值为1。 Speed of zooming / dollying. Default is 1.
controls.maxZoom = 2
controls.minZoom = 0.6
controls.zoomSpeed = 2
复制代码
具体放大系数,可以通过addeventListener
监听并访问camera.zoom
controls.addEventListener("change", changeControls);
function changeControls() {
// console.log(event.type);
console.log('放大值', camera.zoom)
.minDistance
你能够将相机向内移动多少(仅适用于PerspectiveCamera),其默认值为0。
.maxDistance : Float
你能够将相机向外移动多少(仅适用于PerspectiveCamera),其默认值为Infinity。
这相当于透视相机的缩放控制,效果基本等同于正交相机的zoom
演示时用的是 OrthographicCamera
正交相机,使用移动限制需要使用 PerspectiveCamera
透视相机
创建一个透视相机
var Pcamera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
Pcamera.position.set(500, 100, 500); //设置相机位置
scene.add(Pcamera);
复制代码
修改渲染函数中被渲染的相机
// 渲染函数
function render() {
renderer.render(scene, Pcamera); //执行渲染操作
controls.update();
requestAnimationFrame(render);
复制代码
修改控制器控制的相机
var controls = new THREE.OrbitControls(Pcamera, renderer.domElement);
// 设置控制器的移动限制
controls.maxDistance = 250
controls.minDistance = 150
.panSpeed : Float
位移的速度,其默认值为1。
.rotateSpeed : Float
旋转的速度,其默认值为1.
.zoomSpeed : Float
摄像机缩放的速度,其默认值为1。 Speed of zooming / dollying. Default is 1.
mouseButtons
这一对象包含了对用于控制的鼠标按钮的引用。
controls.mouseButtons = {
LEFT: THREE.MOUSE.ROTATE,
MIDDLE: THREE.MOUSE.DOLLY,
RIGHT: THREE.MOUSE.PAN
复制代码
左键旋转,右键移动,滚轮缩放,也可以将LEFT和RIGHT的值换一下,右键旋转,左键移动
screenSpacePanning
定义当平移的时候摄像机的位置将如何移动。如果为true,摄像机将在屏幕空间内平移。 否则,摄像机将在与摄像机向上方向垂直的平面中平移。其默认值为false。
let btn = document.getElementById("btn");
if (btn) {
btn.onclick = function () {
controls.screenSpacePanning = true;
target
控制器的焦点,.object的轨道围绕它运行。 它可以在任何时候被手动更新,以更改控制器的焦点。
let btn = document.getElementById("btn");
if (btn) {
btn.onclick = function () {
let v3 = new THREE.Vector3(0, 0, 0);
setInterval(()=>{
if(v3['y']<50){
controls.target = v3.setY(v3.y+=1)
}, 50)
复制代码
用setInterval可以看到具体移动变化,threejs支持tween.js动画,也可以支持骨骼动画,帧动画等,效果会比setInterval好很多
保存和重置
this.saveState = function () {
scope.target0.copy( scope.target );
scope.position0.copy( scope.object.position );
scope.zoom0 = scope.object.zoom;
this.reset = function () {
scope.target.copy( scope.target0 );
scope.object.position.copy( scope.position0 );
scope.object.zoom = scope.zoom0;
scope.object.updateProjectionMatrix();
scope.dispatchEvent( changeEvent );
scope.update();
state = STATE.NONE;
复制代码
源码中,保存是将target、相机的position、相机的zoom拷贝下来,重置的时候再将这些值赋值给控制器并更新控制器
应用代码:
let save = document.getElementById("save");
let reset = document.getElementById("reset");
if(save && reset){
save.onclick = function (){
controls.saveState()
reset.onclick = function (){
controls.reset()
在保存或者重置时可以单独设置target
target0
由 .saveState : saveState和 .reset : reset方法在内部使用。
zoom0
由 .saveState : saveState和 .reset : reset方法在内部使用。****
position0
由 .saveState : saveState和 .reset : reset方法在内部使用。
dispose
移除所有的事件监听。
this.dispose = function () {
scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false );
scope.domElement.removeEventListener( 'mousedown', onMouseDown, false );
scope.domElement.removeEventListener( 'wheel', onMouseWheel, false );
scope.domElement.removeEventListener( 'touchstart', onTouchStart, false );
scope.domElement.removeEventListener( 'touchend', onTouchEnd, false );
scope.domElement.removeEventListener( 'touchmove', onTouchMove, false );
document.removeEventListener( 'mousemove', onMouseMove, false );
document.removeEventListener( 'mouseup', onMouseUp, false );
scope.domElement.removeEventListener( 'keydown', onKeyDown, false );
//scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
复制代码
取消了所有的监听后,鼠标,键盘等事件对控制器无效
效果相当于禁用控制器
function onMouseDown( event ) {
if ( scope.enabled === false ) return;
// Prevent the browser from scrolling.
event.preventDefault();
......
复制代码
这是部分事件监听方法,如果控制器禁用,就return出去
获取旋转角度
.getAzimuthalAngle () : radians
获得当前的水平旋转,单位为弧度。
.getPolarAngle () : radians
获得当前的垂直旋转,单位为弧度。
controls.addEventListener("change", changeControls);
function changeControls() {
let azimuthal = controls.getAzimuthalAngle ()
console.log('polar', azimuthal);
let polar = controls.getPolarAngle ()
console.log('polar', polar);
复制代码
——学习郭龙邦threejs视频整理
有一起学习的小伙伴,可以留言、关注一起探讨threejs