Scrolling Horizontally in Vue

I am trying to achieve horizontal scrolling through icons using my mouse. I attempted to use scrollLeft in Javascript, but the value remains unchanged while scrolling. Instead, only the deltaY value fluctuates between 100 and -100 during scrolling.

Does anyone have any suggestions on what could be causing this issue?

While scrolling with the mouse over the scrollbar functions correctly, I aim for it to work throughout the entire div-container without relying on external dependencies or npm-libraries if feasible.

Template

<div class="icons flex_center_h flex_between">
     <div class="flex_center_h flex_start instIconContainer"
          @wheel="ScrollIcons($event)">

          <FilterIcon
              v-for="(icon, iconIndex) in rooms[index].description.icons"
                 :key="icon"
                 :icon="rooms[index].description.icons[iconIndex].icon"
                 :customClass="'instIcon'" / 

Javascript

iport {
    FilterIcon
} from '@/components/Elements/'

export default {
    components: {
        FilterIcon,
    },
    computed: {
        rooms() {
            return this.$store.state.rooms
        }

    },
    methods: {
        ScrollIcons(event) {
            event.preventDefault()
            event.target.scrollLeft += event.deltaY
            console.log([event.deltaY, event.target.scrollLeft])
        }
    }
}

Sass

.icons
    background: $bg
    width: 80%
    padding: 0.5rem 0.5rem
    ::-webkit-scrollbar
        width: $scrollbarSize
        height: 0.3rem
        background: $bg-glow
        border-radius: $radius_1
    ::-webkit-scrollbar-thumb
        background: $purple
        border-radius: $radius_1
    .instIconContainer
        width: 70%
        max-width: calc(40px * 4)
        max-height: 80px
        overflow-x: auto
        .instIcon
            width: $IconSize
            height: $IconSize
            min-width: $IconSize
            min-height: $IconSize
            path, circle
                fill: $purple

Console Output when scrolling down

[100, 0]

This is how it looks

https://i.sstatic.net/Tl0fm.png

Answer №1

After experimenting with a method similar to yours, I found that the key to success was switching from using target to currentTarget in the line

event.target.scrollLeft += event.deltaY
within your ScrollIcons function. By making this change, the functionality improved significantly. Now, when navigating with the mouse wheel over the icons, it accurately targets the encompassing div or tag instead of just the icons themselves. Essentially, whenever the cursor hovers over the containing div and the mouse wheel is used, the div responds appropriately, irrespective of any other elements positioned between the div and the cursor.

Answer №2

Your example is facing an issue where event.target is pointing to the icon instead of the scroller element.

To ensure you are targeting the correct element, consider using a ref. 1


Another approach is to bind to the scrollLeft HTML property of the element and delegate DOM updates to Vue. You only need to modify the value in the controller.

We utilize the .camel modifier to handle the case insensitivity of HTML attributes used for property binding: :scroll-left.camel 2, 3

const { createApp, onMounted, reactive, toRefs } = Vue;
const { min, max } = Math;
createApp({
  setup: () => {
    const state = reactive({
      scroller: null,
      scrollLeft: 0,
    });
    const onWheel = (e) => {
      state.scrollLeft = state.scroller
        ? min(
            state.scroller.scrollWidth - state.scroller.offsetWidth,
            max(0, e.deltaY + state.scrollLeft)
          )
        : state.scrollLeft;
    };
    return { ...toRefs(state), onWheel };
  },
}).mount("#app");
#app div span {
  min-width: 50%;
  display: inline-block;
}
#app div {
  display: flex;
  overflow-x: auto;
  cursor: ew-resize;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.37/vue.global.prod.min.js"></script>
<div id="app">
  <div ref="scroller"
       @wheel.prevent="onWheel"
       :scroll-left.camel="scrollLeft">
    <span v-for="n in 5" v-text="n" />
  </div>
  <pre v-text="{ scrollLeft }" />
</div>

Notes:


1 - As we are binding to the scrollLeft prop, the ref might not be necessary anymore. It's included here to limit the controller's scrollLeft value within valid ranges.
2 - Technically, it should be :scroll-left.camel.prop since it's an HTML property, but it also functions without the .prop modifier.
3 - The shorthand form .scroll-left.camel also works (equivalent to :scroll-left.camel.prop).

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Reduce the line length for better readability

Looking for a way to make a button with flexible width while allowing text to wrap to 2 lines for minimum button size? Check out the examples below: To keep the button width small, even short words should wrap to 2 lines: My Button If there's a ...

error is not defined in the onsuccess function of the ajax.beginform partial view

Currently, I am working on an MVC5 project where a View is calling a Partial View. Within the Partial View, there is an Ajax.BeginForm that triggers a function on OnSuccess. However, during execution, I encounter an error stating that the function cannot ...

an li element is accompanied by a visible box

In my possession is a container: #box1 { height:100px; width:208px; } along with a series <li id="first"><strong>FIRST</strong> </li> <li id="second"><strong>SECOND</strong&g ...

Refreshing an HTML table using instance variables from a C# class (utilizing jQuery and AJAX)

Explore <script type="text/javascript"> $(document).ready(function () { $("#viewDetails").click(function () { $.ajax( { type: "POST", url: '@Url.Action("GetDetail", "ControllerName")' ...

Creating a centered floating card within a div that shrinks to fit its contents: A CSS how-to guide

I am facing a challenge with positioning a floating card that needs to be centered over the parent div (which happens to be selectable because it's a map). So far, I have only managed to achieve this by setting a fixed width for the card using the fo ...

Exploring the depths of recursion with jQuery: Unraveling the

Having some issues with a recursive function in jQuery that's throwing an exception: 'Uncaught RangeError: Maximum call stack size exceeded' I can't figure out why this recursive function might be running infinitely. Any help would be ...

Activate an alert function when the text inside a div reaches the value of 10

Currently, I am developing a game where once a player reaches 10 strikes, an alert should pop up saying "Game Over". However, the alert function is not working as expected. The StrikeNumber ID corresponds to the DIV that should trigger the alert once it ...

The specified element "errors" is not found in the VeeValidate template

Trying to use VeeValidate for field validation in a Vue form with Vue 2.5 and VeeValidate 2.1, the following method is used: <input class="form-control" name="contact-email" id="contact-email" type="email" v-model="contact-email" v-validate="'re ...

Is combining a DateTime with a time string possible using Luxon?

I have a component called TimePicker that provides time in 24-hour format like 09:00 for 9 AM, 12:00 for 12 PM, or 20:00 for 8 PM. In my code, I need to convert this time into a Date (JSDate) by combining it with the current date and time using DateTime.no ...

Tips for adjusting the color of a row when hovering

Can I modify the row color on hover in material-table using props? Similar to this example. Appreciate your help. ...

What could be causing the hang when attempting to insert a script using Bookshelf.js?

Can anyone help me understand why the Node.js script refuses to exit? // myscript.js var Model = bookshelf.Model.extend({ tableName: 'models' }); var m = Model.forge({name: 'hello'}); m.save(); console.log("End"); Even after running ...

Notification following the closure of a modal page in APEX version 23.1

Is there a way to display a message when the close button (X) on a modal dialog is clicked? Please note that I cannot use the dialog closed event as I specifically want to target the X button and not the cancel button! ...

Using jQuery to manipulate the radio button input's alternate content in HTML attributes

How can I use Jquery Attr.Radio Button click to write to the div with id #RadioDesc? <input type="radio" desc="sample description" class="AddText"> <script type="text/javascript"> $( document ).ready( function() { $("radio").click ...

The divs are causing the site to grow larger and are not lining up correctly

My problem arises from the challenge of aligning my sidebar and a table vertically. Despite attempting to use float: left on the table, it only expanded the site width without properly aligning them side by side within Bootstrap, CSS, and HTML constraints. ...

Redirecting Permalinks on a WordPress Website

I run a WordPress website called example.com and I have set up a redirect to beta.example.com. My goal is to display my links as example.com/link1 instead of the previous beta.example.com/link1. I am currently using <?php echo get_permalink(id); ?> ...

Tips on integrating data from Vuex into your component

How can I effectively utilize the data fetched using the Vuex store's action in a specific component? import axios from 'axios' export default { namespaced: true, state: { items: [] }, actions: { fetchCategories ({state, c ...

Divide the firestore request into multiple filters

I am currently developing a filter system that allows users to search for specific parameters without filling out the entire form. For instance, they could search for games of a certain type but across all genres (leaving the form empty results in an empty ...

Using three.js to establish an Image for Particle

I am looking to make some changes to this demo: Instead of having colored particles, I want to assign an image to each one. Should I use a cube for this purpose? Or is there a way to use an image with Vector3? Here is the code for the example: i ...

Encountering issues while trying to access 'weather' in NuxtJS API call due to undefined properties

I'm having an issue with the Open Weather API where I keep getting this error: Cannot read properties of undefined (reading 'weather'). Strangely, the error disappears when I move the v-list section to another page. Here is the code snippet ...

Discover the steps to dynamically alter the inclusion of the Bootstrap CSS file within an Angular project

I manage a multi-language website in both English (EN) and Arabic (AR). Currently, I am utilizing Bootstrap CSS from a CDN and adjusting the CDN link based on the selected language. index.html <!DOCTYPE html> <html lang="en"> <h ...