@@ -52,6 +52,14 @@ class OrbitControls extends EventDispatcher<StandardControlsEventMap> {
5252 // If damping is enabled, you must call controls.update() in your animation loop
5353 enableDamping = false
5454 dampingFactor = 0.05
55+ /**
56+ * The static friction force applied to the movement.
57+ * This is a constant force that opposes movement, independent of speed.
58+ *
59+ * @type {number }
60+ * @default 0
61+ */
62+ staticMovingFriction = 0
5563 // This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
5664 // Set to false to disable zooming
5765 enableZoom = true
@@ -307,6 +315,33 @@ class OrbitControls extends EventDispatcher<StandardControlsEventMap> {
307315 sphericalDelta . phi *= 1 - scope . dampingFactor
308316
309317 panOffset . multiplyScalar ( 1 - scope . dampingFactor )
318+
319+ if ( scope . staticMovingFriction > 0 ) {
320+ const thetaSign = Math . sign ( sphericalDelta . theta )
321+ if ( thetaSign !== 0 ) {
322+ sphericalDelta . theta -= thetaSign * scope . staticMovingFriction
323+ if ( Math . sign ( sphericalDelta . theta ) !== thetaSign ) {
324+ sphericalDelta . theta = 0
325+ }
326+ }
327+
328+ const phiSign = Math . sign ( sphericalDelta . phi )
329+ if ( phiSign !== 0 ) {
330+ sphericalDelta . phi -= phiSign * scope . staticMovingFriction
331+ if ( Math . sign ( sphericalDelta . phi ) !== phiSign ) {
332+ sphericalDelta . phi = 0
333+ }
334+ }
335+
336+ const panLen = panOffset . length ( )
337+ if ( panLen > 0 ) {
338+ if ( panLen > scope . staticMovingFriction ) {
339+ panOffset . multiplyScalar ( ( panLen - scope . staticMovingFriction ) / panLen )
340+ } else {
341+ panOffset . set ( 0 , 0 , 0 )
342+ }
343+ }
344+ }
310345 } else {
311346 sphericalDelta . set ( 0 , 0 , 0 )
312347
0 commit comments