Skip to content

Commit 1e38727

Browse files
feat: add rubberbandIfOutOfBounds (#414)
1 parent 1a7cb8a commit 1e38727

1 file changed

Lines changed: 43 additions & 2 deletions

File tree

src/core/bounds/bounds.utils.ts

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,36 @@ export const calculateBounds = (
9191
return bounds;
9292
};
9393

94+
export function clamp(v: number, min: number, max: number) {
95+
return Math.max(min, Math.min(v, max));
96+
}
97+
98+
// Based on @aholachek ;)
99+
// https://twitter.com/chpwn/status/285540192096497664
100+
// iOS constant = 0.55
101+
102+
// https://medium.com/@nathangitter/building-fluid-interfaces-ios-swift-9732bb934bf5
103+
104+
function rubberband(distance: number, dimension: number, constant: number) {
105+
if (dimension === 0 || Math.abs(dimension) === Infinity)
106+
return distance ** (constant * 5);
107+
return (distance * dimension * constant) / (dimension + constant * distance);
108+
}
109+
110+
export function rubberbandIfOutOfBounds(
111+
position: number,
112+
min: number,
113+
max: number,
114+
constant = 0.15,
115+
) {
116+
if (constant === 0) return clamp(position, min, max);
117+
if (position < min)
118+
return -rubberband(min - position, max - min, constant) + min;
119+
if (position > max)
120+
return +rubberband(position - max, max - min, constant) + max;
121+
return position;
122+
}
123+
94124
/**
95125
* Keeps value between given bounds, used for limiting view to given boundaries
96126
* 1# eg. boundLimiter(2, 0, 3, true) => 2
@@ -140,15 +170,26 @@ export function getMouseBoundedPosition(
140170
paddingY = paddingValueY;
141171
}
142172

143-
const x = boundLimiter(
173+
const rubberbandX = rubberbandIfOutOfBounds(
144174
positionX,
175+
minPositionX,
176+
maxPositionX,
177+
);
178+
const rubberbandY = rubberbandIfOutOfBounds(
179+
positionY,
180+
minPositionY,
181+
maxPositionY,
182+
);
183+
184+
const x = boundLimiter(
185+
rubberbandX,
145186
minPositionX - paddingX,
146187
maxPositionX + paddingX,
147188
limitToBounds,
148189
);
149190

150191
const y = boundLimiter(
151-
positionY,
192+
rubberbandY,
152193
minPositionY - paddingY,
153194
maxPositionY + paddingY,
154195
limitToBounds,

0 commit comments

Comments
 (0)