Horizontal Scrolling with Mouse Wheel in a Div

Horizontal scroll with mouse wheel on horizontal list

You just forget to add JQuery to your html

http://jsfiddle.net/902tjbzz/

jquery.js : http://code.jquery.com/jquery-2.1.4.min.js

How to horizontally scroll a table with mouse wheel in react?

Use onWheel event

The onwheel event occurs when the mouse wheel is rolled up or down over an element.

With Element.scrollTo(), Element.scrollLeft

The scrollTo() method of the Element interface scrolls to a particular set of coordinates inside a given element.

element.scrollTo({
top: 100,
left: 100,
behavior: 'smooth'
});

Code sample:

const onWheel = e => {
e.preventDefault();
const container = document.getElementById("container");
const containerScrollPosition = document.getElementById("container").scrollLeft;
container.scrollTo({
top: 0,
left: containerScrollPosition + e.deltaY,
behaviour: "smooth"
});
};

<div className="container" id="container" onWheel={onWheel}>

Sample Image

Refer: Horizontal Scrolling on React Component Using Vertical Mouse Wheel

How to do React-horizontal scroll using mouse wheel

You can use a custom scroll function as a ref to your div.

export function useHorizontalScroll() {
const elRef = useRef();
useEffect(() => {
const el = elRef.current;
if (el) {
const onWheel = e => {
if (e.deltaY == 0) return;
e.preventDefault();
el.scrollTo({
left: el.scrollLeft + e.deltaY,
behavior: "smooth"
});
};
el.addEventListener("wheel", onWheel);
return () => el.removeEventListener("wheel", onWheel);
}
}, []);
return elRef;
}

The above function can be imported and used as follows:

    <div className="App" ref={scrollRef} style={{ overflow: "auto" }}>
<div style={{ whiteSpace: "nowrap" }}>
<Picture />
</div>
</div>

I created a codesandbox as an example.

react horizontal scroll to section with mouse wheel

I've modified your sandbox Working Demo.

Did following changes:

  • Created navRefs for each menu item. And did the same thing with navRefs as you did with scrollRefs.
// called it when user scrolls vertically, or clicks on a menu item
navRefs.current[i].current.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "center"
});
  • Changed logic to find currently focused content.
const isVisible =
elemTop < window.innerHeight / 2 && elemBottom > window.innerHeight / 2;

In short if content is on viewport's horizontal center then select it. This avoids selecting multiple contents if many of them are in viewport at the same time.

  • Used a flag to avoid executing scrollHandler when user clicks on a menu item. Also avoided the horizontal scroll events on navbar.
  • In CSS hide horizontal scrollbar on navbar. And added red underline to selected menu item.
Code for ready reference:
import "./styles.css";

import React, { createRef, useRef, useState, useEffect } from "react";

var scrolling = false;

export default function App() {
const scrollRefs = useRef([]);
const navRefs = useRef([]);

const [active, setActive] = useState(0);

const list = [
"Item 1",
"Item 2",
"Item 3",
"Item 4",
"Item 5",
"Item 6",
"Item 7",
"Item 8",
"Item 9",
"Item 10"
];

scrollRefs.current = [...Array(list.length).keys()].map(
(_, i) => scrollRefs.current[i] ?? createRef()
);

navRefs.current = [...Array(list.length).keys()].map(
(_, i) => navRefs.current[i] ?? createRef()
);

const scrollTo = (index) => {
console.log("setting scrolling" + scrolling);
scrolling = true;
scrollRefs.current[index].current.scrollIntoView({ behavior: "smooth" });
setActive(index);
setTimeout(() => {
scrolling = false;
navRefs.current[index].current.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "center"
});
}, 1000);
};

const scrollHandler = (e) => {
// handle scroll only on body
// we don't want to handle horizontal scroll on nav bar
if (e.target !== document) return;

if (scrolling === true) return;

const scrollRefsElements = scrollRefs.current;

scrollRefsElements.forEach((el, i) => {
const rect = el.current.getBoundingClientRect();
const elemTop = rect.top;
const elemBottom = rect.bottom;
const isVisible =
elemTop < window.innerHeight / 2 && elemBottom > window.innerHeight / 2;

if (isVisible) {
navRefs.current[i].current.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "center"
});
setActive(i);
}
});
};

useEffect(() => {
window.addEventListener("scroll", scrollHandler, true);
return () => {
window.removeEventListener("scroll", scrollHandler, true);
};
}, []);

return (
<div className="container">
<ul className="myMenu nav list-unstyled d-flex flex-nowrap fixed-top">
{list.map((item, i) => (
<li className="nav-item " key={i} ref={navRefs.current[i]}>
<a
href={`#s-${i}`}
className={`nav-link text-nowrap ${
active === i ? "text-danger" : ""
}`}
onClick={(e) => {
scrollTo(i);
}}
>
{item}
</a>
</li>
))}
</ul>

<ul className="mb-100 list-unstyled">
{list.map((item, i) => (
<li id={`s-${i}`} ref={scrollRefs.current[i]} className="py-100 px-3">
<h3>{item}</h3>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nisi,
dicta.
</p>
</li>
))}
</ul>
</div>
);
}

Horizontal Scrolling on React Component Using Vertical Mouse Wheel

Okay, so the issue seems to be that you only refer to the function event.preventDefault rather than invoking it.
Adding some brackets at the end to invoke it should do the trick:
event.preventDefault().

I however found this issue while looking for some simple code to use, so I will also leave the hook I made for this if others in the same situation:

import { useRef, useEffect } from "react";

export function useHorizontalScroll() {
const elRef = useRef();
useEffect(() => {
const el = elRef.current;
if (el) {
const onWheel = e => {
if (e.deltaY == 0) return;
e.preventDefault();
el.scrollTo({
left: el.scrollLeft + e.deltaY,
behavior: "smooth"
});
};
el.addEventListener("wheel", onWheel);
return () => el.removeEventListener("wheel", onWheel);
}
}, []);
return elRef;
}

Usage:

import React from "react";
import { useSideScroll } from "./useSideScroll";

export const SideScrollTest = () => {
const scrollRef = useHorizontalScroll();
return (
<div ref={scrollRef} style={{ width: 300, overflow: "auto" }}>
<div style={{ whiteSpace: "nowrap" }}>
I will definitely overflow due to the small width of my parent container
</div>
</div>
);
};

Note:
The scroll behavior "smooth" seems to be giving some trouble when trying to do continuous scrolling. This behavior can be omitted to have proper continuous scrolling, but it will look jerky.

As far as I know, there is no easy solution for this. I have however created a rather involved solution in my own project, so thought some people may appreciate that also: https://gist.github.com/TarVK/4cc89772e606e57f268d479605d7aded

Horizontal scrolling with mouse wheel and button in a div

Thank you for anyone who paying attention to my problems. I have solved this by myself luckily. This is the answer how i solve it.

onWheel(event: WheelEvent): void {
this.widgetsContent.nativeElement.scrollLeft += event.deltaY;
event.preventDefault();
}

How to do a horizontal scroll on mouse wheel scroll?

It looks like he's just mapping the mousewheel event to scrolling the area. In IE, this is really easy by just using the doScroll() method - this will scroll the horizontal bar by the amount the vertical bar would normally scroll by. Other browsers don't support the doScroll() method, so you have to live with scrolling by an arbitrary amount instead:

var mouseWheelEvt = function (event) {
if (document.body.doScroll)
document.body.doScroll(event.wheelDelta>0?"left":"right");
else if ((event.wheelDelta || event.detail) > 0)
document.body.scrollLeft -= 10;
else
document.body.scrollLeft += 10;

return false;
}
document.body.addEventListener("mousewheel", mouseWheelEvt);


Related Topics



Leave a reply



Submit