summaryrefslogtreecommitdiff
path: root/js/mx/mx.followingOrbitCamera.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/mx/mx.followingOrbitCamera.js')
-rw-r--r--js/mx/mx.followingOrbitCamera.js148
1 files changed, 148 insertions, 0 deletions
diff --git a/js/mx/mx.followingOrbitCamera.js b/js/mx/mx.followingOrbitCamera.js
new file mode 100644
index 0000000..ea7f6a0
--- /dev/null
+++ b/js/mx/mx.followingOrbitCamera.js
@@ -0,0 +1,148 @@
+MX.FollowingOrbitCamera = function(opt){
+ var exports = {}, bound = false, portraitMode = false
+ var locked = false
+ exports.opt = opt = defaults(opt, {
+ el: window, // object to bind events on
+ camera: scene.camera, // camera object we'll be moving
+ radius: 100,
+ radiusRange: [ 10, 1000 ],
+ rotationX: Math.PI/2,
+ rotationY: 0,
+ rotationXRange: [ 0, 1 ],
+ rotationYRange: [ 0, 1 ],
+ center: { x: 0, y: 0, z: 0 },
+ sensitivity: 10, // moving 1 pixel is like moving N radians
+ wheelSensitivity: 10,
+ ease: 10,
+ })
+ opt.rotationXRange[0] *= Math.PI
+ opt.rotationXRange[1] *= Math.PI
+ opt.rotationYRange[0] *= Math.PI
+ opt.rotationYRange[1] *= Math.PI
+ var rx, ry, radius, px, py, epsilon = 1e-5, dragging = false
+ exports.init = function(){
+ opt.rotationY = ry = ( opt.rotationYRange[0] + opt.rotationYRange[1] ) / 2
+ opt.rotationX = rx = ( opt.rotationXRange[0] + opt.rotationXRange[1] ) / 2
+ radius = opt.radius
+ exports.wheel = new wheel({
+ el: opt.el,
+ update: function(e, delta){
+ if (locked) return
+ opt.radius = clamp( opt.radius + delta * opt.wheelSensitivity, opt.radiusRange[0], opt.radiusRange[1] )
+ },
+ })
+ exports.bind()
+ }
+ exports.toggle = function(state){
+ if (state) exports.bind()
+ else exports.unbind()
+ }
+ exports.lock = function(){
+ locked = true
+ }
+ exports.unlock = function(){
+ locked = false
+ }
+ exports.bind = function(){
+ if (bound) return;
+ bound = true
+ // opt.el.addEventListener("mousedown", down)
+ if (is_mobile) {
+ if ('DeviceOrientationEvent' in window) {
+ window.addEventListener("resize", resize)
+ window.addEventListener("deviceorientation", deviceorientation)
+ resize()
+ }
+ }
+ else {
+ window.addEventListener("mousemove", move)
+ }
+ // window.addEventListener("mouseup", up)
+ exports.wheel.unlock()
+ }
+ exports.unbind = function(){
+ if (! bound) return;
+ bound = false
+ // opt.el.removeEventListener("mousedown", down)
+ window.removeEventListener("mousemove", move)
+ // window.removeEventListener("mouseup", up)
+ exports.wheel.lock()
+ }
+ // function down (e) {
+ // px = e.pageX
+ // py = e.pageY
+ // dragging = true
+ // }
+ function move (e) {
+ // if (! dragging) return
+ // exports.delta(px - e.pageX, py - e.pageY)
+ if (locked) return
+ exports.delta( e.pageX, e.pageY)
+ px = e.pageX
+ py = e.pageY
+ }
+ function resize (e) {
+ var aspect = window.innerHeight / window.innerWidth;
+ portraitMode = aspect >= 1;
+ }
+ function deviceorientation (e){
+ if (e && 'beta' in e && e.beta) {
+ var b, g
+ if (portraitMode) {
+ b = e.beta
+ g = e.gamma
+ } else {
+ b = e.gamma
+ g = e.beta
+ }
+
+ // console.log(b, g)
+ }
+ }
+ // function up (e) {
+ // dragging = false
+ // }
+ exports.delta = function(x,y){
+ // opt.rotationY += x/window.innerWidth * opt.sensitivity
+ // opt.rotationX = clamp( opt.rotationX + y/window.innerHeight * opt.sensitivity, 0, Math.PI)
+ opt.rotationY = lerp( x / window.innerWidth, opt.rotationYRange[0], opt.rotationYRange[1] )
+ opt.rotationX = lerp( y / window.innerHeight, opt.rotationXRange[0], opt.rotationXRange[1] )
+ }
+ exports.zoom = function(r){
+ opt.radius = r
+ }
+ exports.zoomDelta = function(r){
+ opt.radius += r
+ }
+ exports.move = function(y, x){
+ opt.rotationY = y
+ if (typeof x == "number") { opt.rotationX = x }
+ }
+ exports.update = function(){
+ if (locked) return
+ if (Math.abs(ry - opt.rotationY) > epsilon) {
+ ry = avg(ry, opt.rotationY, opt.ease)
+ }
+ else {
+ ry = opt.rotationY
+ }
+ if (Math.abs(rx - opt.rotationX) > epsilon) {
+ rx = avg(rx, opt.rotationX, opt.ease)
+ }
+ else {
+ rx = opt.rotationX
+ }
+ if (Math.abs(radius - opt.radius) > epsilon) {
+ radius = avg(radius, opt.radius, opt.ease)
+ }
+ else {
+ radius = opt.radius
+ }
+ opt.camera.x = opt.center.x + radius * Math.sin(rx) * Math.cos(ry)
+ opt.camera.z = opt.center.y + radius * Math.sin(rx) * Math.sin(ry)
+ opt.camera.y = opt.center.z + radius * Math.cos(rx)
+ opt.camera.rotationX = Math.PI/2 - rx
+ opt.camera.rotationY = ry + Math.PI/2
+ }
+ return exports
+}