Adding smooth scroll on my scrollable div - javascript

I have a div block containing the steps of one of my benefits that I made scrollable vertically by holding with the mouse ( Draggable Div )
I would like to add a smooth effect and not just a scroll that stops instantly when we stop the scroll.
What should I add to my code below?
Thank you and happy holidays! šŸŽ…šŸ»šŸŽ„
const container = document.querySelector('.process-steps');
let startY;
let startX;
let scrollLeft;
let scrollTop;
let isDown;
container.addEventListener('mousedown',e => mouseIsDown(e));
container.addEventListener('mouseup',e => mouseUp(e))
container.addEventListener('mouseleave',e=>mouseLeave(e));
container.addEventListener('mousemove',e=>mouseMove(e));
function mouseIsDown(e){
isDown = true;
startY = e.pageY - container.offsetTop;
startX = e.pageX - container.offsetLeft;
scrollLeft = container.scrollLeft;
scrollTop = container.scrollTop;
}
function mouseUp(e){
isDown = false;
}
function mouseLeave(e){
isDown = false;
}
function mouseMove(e){
if(isDown){
e.preventDefault();
//Move vertcally
const y = e.pageY - container.offsetTop;
const walkY = y - startY;
container.scrollTop = scrollTop - walkY;
}
}
</script>

Related

Stop Click event after Dragging on Slider

Iā€™ve been struggling to solve this for days now. There is a slider with clickable items at the bottom of the page. Iā€™ve made the slider draggable. But the issue is that when the dragging stops the click action also happens on the item on which mousedown event happened. Iā€™ve tried to adding ā€˜pointer-vents: noneā€™ to the inner item after dragging starts, but in this case draggint doesnā€™t work at all. Any ideas on how can I solve this problem?
https://duolutions-wondrous-site.webflow.io/straudo-branding-naming
Read-Only link of webflow: https://preview.webflow.com/preview/duolutions-wondrous-site?utm_medium=preview_link&utm_source=designer&utm_content=duolutions-wondrous-site&preview=9e5312190b70be978f65b8da04fbcefc&pageId=6377be41955fe23fb7c4bf33&workflow=preview
<script>
let isDown = false;
let startX;
let scrollLeft;
const slider = document.querySelector('.items');
const end = () => {
isDown = false;
slider.classList.remove('active');
}
const start = (e) => {
isDown = true;
slider.classList.add('active');
startX = e.pageX || e.touches[0].pageX - slider.offsetLeft;
scrollLeft = slider.scrollLeft;
}
const move = (e) => {
if(!isDown) return;
e.preventDefault();
const x = e.pageX || e.touches[0].pageX - slider.offsetLeft;
const dist = (x - startX);
slider.scrollLeft = scrollLeft - dist;
}
(() => {
slider.addEventListener('mousedown', start);
slider.addEventListener('touchstart', start);
slider.addEventListener('mousemove', move);
slider.addEventListener('touchmove', move);
slider.addEventListener('mouseleave', end);
slider.addEventListener('mouseup', end);
slider.addEventListener('touchend', end);
})();
</script>
There is no link to a working sandbox, so I can't be sure it will help, but I've noticed you didn't use Event.stopPropagation(). This should stop the propagation of the current event. You can read more about it here

Horizontal click and drag scroller for multiple sections help, works for only one

So I have a horizontal scrolling feature which works great in JS but only for one section with the classname, any other section that shares the same classname it doesn't replicate the same effects for. How can I make it so it works for every section that has the class name. You can see it in action on my website here where the quick links scrolls fine when you click but the other horizontally scrolling sections dont. Thank you - https://tutoryou.uixweb.dev/
const slider = document.querySelector('.scroller-div');
let mouseDown = false;
let startX, scrollLeft;
let startDragging = function (e) {
mouseDown = true;
startX = e.pageX - slider.offsetLeft;
scrollLeft = slider.scrollLeft;
};
let stopDragging = function (event) {
mouseDown = false;
};
slider.addEventListener('mousemove', (e) => {
e.preventDefault();
if(!mouseDown) { return; }
const x = e.pageX - slider.offsetLeft;
const scroll = x - startX;
slider.scrollLeft = scrollLeft - scroll;
});
// Add the event listeners
slider.addEventListener('mousedown', startDragging, false);
slider.addEventListener('mouseup', stopDragging, false);
slider.addEventListener('mouseleave', stopDragging, false);
for smooth scrolling (no jump effect) you have to create variables inside forEach()
const sliders = document.querySelectorAll('.scroller-div');
sliders.forEach(slider=>{
let startX, scrollLeft;
let startDragging = function(e) {
mouseDown = true;
startX = e.pageX - slider.offsetLeft;
scrollLeft = slider.scrollLeft;
};
let stopDragging = function(event) {
mouseDown = false;
};
slider.addEventListener('mousemove', (e)=>{
e.preventDefault();
if (!mouseDown) {
return;
}
const x = e.pageX - slider.offsetLeft;
const scroll = x - startX;
slider.scrollLeft = scrollLeft - scroll;
}
);
// Add the event listeners
slider.addEventListener('mousedown', startDragging, false);
slider.addEventListener('mouseup', stopDragging, false);
slider.addEventListener('mouseleave', stopDragging, false);
}
);
First change this:
const slider = document.querySelector('.scroller-div');
To this:
const sliders = document.querySelectorAll('.scroller-div');
querySelector will stop after finding the first element matching your selector while querySelectorAll will return a list of all the elements matching your selector.
Once you do that, you will need to loop through all the sliders and add the event listener to each one. So your code becomes wrapped in a forEach loop:
sliders.forEach(slider => {
let mouseDown = false;
let startX, scrollLeft;
let startDragging = function (e) {
mouseDown = true;
startX = e.pageX - slider.offsetLeft;
scrollLeft = slider.scrollLeft;
};
let stopDragging = function (event) {
mouseDown = false;
};
slider.addEventListener('mousemove', (e) => {
e.preventDefault();
if(!mouseDown) { return; }
const x = e.pageX - slider.offsetLeft;
const scroll = x - startX;
slider.scrollLeft = scrollLeft - scroll;
});
// Add the event listeners
slider.addEventListener('mousedown', startDragging, false);
slider.addEventListener('mouseup', stopDragging, false);
slider.addEventListener('mouseleave', stopDragging, false);
});

Can't update my mouse position, because of my horizontal scroll (LocomotiveScroll)

I'm trying to make a custom cursor with the Ink Cursor by Ricardo Mendieta. https://codepen.io/mendieta/pen/WgvENJ
The cursor is working, but the problem I have is that I use a horizontal scroll with Locomotive Scroll. When I scroll, the mouse position doesn't get updated. I tried to fix this with a mousewheel function. I can console log the mousewheel event, but it doesn't update my mouse position.
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mousewheel', onMouseScroll);
const onMouseMove = (event) => {
mousePosition.x = event.clientX - width / 2;
mousePosition.y = event.clientY - width / 2;
resetIdleTimer();
};
const onMouseScroll = (event) => {
console.log(event);
mousePosition.x = event.clientX - width / 2;
mousePosition.y = event.clientY - width / 2;
resetIdleTimer();
};
const render = (timestamp) => {
const delta = timestamp - lastFrame;
positionCursor(delta);
lastFrame = timestamp;
requestAnimationFrame(render);
};
const positionCursor = (delta) => {
let x = mousePosition.x;
let y = mousePosition.y;
dots.forEach((dot, index, dots) => {
let nextDot = dots[index + 1] || dots[0];
dot.x = x;
dot.y = y;
dot.draw(delta);
if (!idle || index <= sineDots) {
const dx = (nextDot.x - dot.x) * 0.35;
const dy = (nextDot.y - dot.y) * 0.35;
x += dx;
y += dy;
}
});
};
Is there a way I can update the mouse position when I scroll when the scroll direction is horizontal.
I just figured this out for my situation, which I think is similar to yours. Not sure if this will help or not - hopefully it does.
scroll.on('scroll', (instance) => {
let customCursor = document.querySelector(".customCursor");
let scrollPx = instance.scroll.x + "px";
customCursor.style.left = scrollPx;
});
So instead of trying to reconfigure where the mouse position is, I'm simply updating the "left" attribute of the custom cursor to be in sync with how much the horizontally laid out Locomotive scroll container is being scrolled.

Click and drag scroll to have momentum when releasing

Two things I need are that you could choose the speed of the scroll when dragging and upon release it would still move a bit, not stop instantly.
codepen: https://codepen.io/rKaiser/pen/qGomdR
I can set the speed close enough. Reasonable to add some momentum? or perhaps there is a more fitting plugin to use here? Thanks.
const slider = document.querySelector('.container');
let isDown = false;
let startX;
let scrollLeft;
slider.addEventListener('mousedown', (e) => {
isDown = true;
slider.classList.add('active');
startX = e.pageX - slider.offsetLeft;
scrollLeft = slider.scrollLeft;
});
slider.addEventListener('mouseleave', () => {
isDown = false;
slider.classList.remove('active');
});
slider.addEventListener('mouseup', () => {
isDown = false;
slider.classList.remove('active');
});
slider.addEventListener('mousemove', (e) => {
if(!isDown) return;
e.preventDefault();
const x = e.pageX - slider.offsetLeft;
const walk = (x - startX) * 0.3; //scroll-speed
slider.scrollLeft = scrollLeft - walk;
});
You need to increase scrollLeft with certain amount with every frame, after mouseup, till speed becomes 0. Something like=>
slider.addEventListener('mouseup', () => {
isDown = false;
slider.classList.remove('active');
speed = (-scrollLeft+slider.scrollLeft)/(new Date()-t)*500; //t is time of mouse down start
const draw=()=>{
if(speed>0){
slider.scrollLeft = slider.scrollLeft + speed--; //increase by certain amount
}else{
momentum=false;
}
requestAnimationFrame(draw);
}
momentum=true;
draw();
});
slider.addEventListener('mousemove', (e) => {
if(!isDown && !momentum){
return;
}..

On each mousemove, the draggable element positioning is getting reset to zero

I'm working on a component that moves a parts diagram around in a container. Right now everything works great on the first mousemove, but on the second the positioning styles are getting reset to zero.
I re-wrote the code outside of Vue and also made a codepen for your viewing.
Codepen: https://codepen.io/paytonburd/pen/WKqEjo
Code:
let diagram = document.getElementById('diagram')
let diagramImg = document.getElementById('diagram-image')
let startX;
let startY;
let walkX;
let walkY;
let dragging = false;
diagram.addEventListener('mousedown', (e) => {
dragging = true;
startX = e.pageX - diagram.offsetLeft;
startY = e.pageY - diagram.offsetTop;
})
diagram.addEventListener('mousemove', (e) => {
if (!dragging) return;
e.preventDefault();
let x = e.pageX - diagram.offsetLeft;
let y = e.pageY - diagram.offsetTop;
walkX = x - startX
walkY = y - startY
console.log(walkX, walkY)
diagramImg.style.top = walkY + 'px'
diagramImg.style.left = walkX + 'px'
})
diagram.addEventListener('mouseleave', () => {
dragging = false;
})
diagram.addEventListener('mouseup', () => {
dragging = false;
})
When you mouse down, you always set the startX and startY relative to the position of the diagram, which is always at 0, 0 and never moves.
I think what you want is to instead set them to relative to the current position of the diagram image instead:
let diagram = document.getElementById('diagram')
let diagramImg = document.getElementById('diagram-image')
let startX;
let startY;
let walkX;
let walkY;
let dragging = false;
diagram.addEventListener('mousedown', (e) => {
dragging = true;
//This is where it went wrong
startX = e.pageX - diagramImg.offsetLeft;
startY = e.pageY - diagramImg.offsetTop;
})
diagram.addEventListener('mousemove', (e) => {
if (!dragging) return;
e.preventDefault();
let x = e.pageX - diagram.offsetLeft;
let y = e.pageY - diagram.offsetTop;
walkX = x - startX
walkY = y - startY
console.log(walkX, walkY)
diagramImg.style.top = walkY + 'px'
diagramImg.style.left = walkX + 'px'
})
diagram.addEventListener('mouseleave', () => {
dragging = false;
})
diagram.addEventListener('mouseup', () => {
dragging = false;
})
https://codepen.io/anon/pen/yqdzyq?editors=1111

Categories