-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feature] Scroll speed according to distance from edge #1907
Comments
@koraykural Can you post your work-around implementation of |
Sorry, I could not find it. It was an old project. |
@gap777 Well, I made something work-around implementation that scroll speed increases gradually. It also considers the mouse position outside of window. If u need it, just adjust some codes below const onStart = (e) => {
startScrollFn(e);
};
const onEnd = (e) => {
initScrollVars();
};
type Direction = "up" | "down" | "right" | "left";
let pointerId: number;
let targetScrollEl: HTMLElement | null;
let lastPointerEvent: PointerEvent;
let interval;
let scrollSpeed = 3;
const speedIncreaseFactor = 0.001;
let lastMoveDirection: Direction;
const initScrollSpeed = () => (scrollSpeed = 3);
const onMouseMove = (event: PointerEvent) => {
if (targetScrollEl) {
lastPointerEvent = event;
}
};
const startScrollFn = (e) => {
const context = e.from as HTMLDivElement;
pointerId = e.originalEvent.pointerId;
targetScrollEl = getClosestScrollableEl(context);
if (targetScrollEl) {
targetScrollEl.setPointerCapture(pointerId);
targetScrollEl.addEventListener("pointermove", onMouseMove);
clearInterval(interval);
interval = setInterval(() => {
scrollFn(lastPointerEvent, targetScrollEl);
});
}
};
const initScrollVars = () => {
if (targetScrollEl?.hasPointerCapture(pointerId)) {
targetScrollEl?.releasePointerCapture(pointerId);
}
targetScrollEl?.removeEventListener("pointermove", onMouseMove);
targetScrollEl = null;
initScrollSpeed();
clearInterval(interval);
};
const scrollFn = (e: PointerEvent, container: HTMLElement | null) => {
if (!container || !e) return false;
targetScrollEl = container;
const { moveDirection, x, y } = getScrollResult(container, e);
container.scrollBy(x, y);
if (e !== lastPointerEvent) {
scrollSpeed = round(scrollSpeed + speedIncreaseFactor, 3);
}
if (moveDirection !== lastMoveDirection) {
initScrollSpeed();
}
if (moveDirection) lastMoveDirection = moveDirection;
return false;
};
const getScrollResult = (container: HTMLElement, e: PointerEvent) => {
let moveDirection: Direction | null = null;
let x = 0;
let y = 0;
const scrollSensitivity = props.option?.scrollSensitivity || 50;
const { top, bottom, left, right } = container.getBoundingClientRect();
const topDistance = e.clientY - top;
const bottomDistance = bottom - e.clientY;
const leftDistance = e.clientX - left;
const rightDistance = right - e.clientX;
if (topDistance < scrollSensitivity) {
y = (-(scrollSensitivity - topDistance) / scrollSensitivity) * scrollSpeed;
moveDirection = "up";
} else if (bottomDistance < scrollSensitivity) {
y =
((scrollSensitivity - bottomDistance) / scrollSensitivity) * scrollSpeed;
moveDirection = "down";
}
if (leftDistance < scrollSensitivity) {
x = (-(scrollSensitivity - leftDistance) / scrollSensitivity) * scrollSpeed;
moveDirection = "left";
} else if (rightDistance < scrollSensitivity) {
x = ((scrollSensitivity - rightDistance) / scrollSensitivity) * scrollSpeed;
moveDirection = "right";
}
return { moveDirection, x, y };
}; FYI, It's actually for Vue components and used customized Sortable so some function's parameters might be different from original. You also have to call the method <draggable
:scroll-fn="(e, container)=>scrollFn(e, container)"
>
</draggable> something like this |
Currently scroll speed is either 0 or the specified
scrollSpeed
if dragged item is near to edge.Requested feature is that scroll speed will increase gradually according to the distance to the edge. If it's closer, it will be faster.
This can be done probably with
scrollFn
property but it would be much better if there were some built in functions like'linear'
,'ease-in'
,'ease-out'
etc.The text was updated successfully, but these errors were encountered: