Двигаться, прокручивая 3 элемента с 1 обработчиком событий

Я пытаюсь переместить 3 полосы прокрутки из 3 <div class = "container"> по имени класса с одним и тем же событием за один раз. Это мой подход: В первую очередь делюсь обработчиком событий из скрипта

function handleScroll(event: any) {
  let position: number = event._vts
  let scrollOptions = {
    left: position,
    top: 0,
    behavior: undefined
  }

  if (event._vts) {
    if (graficas.length !== 0) {
      console.info('muevo el array')
      console.info('asi tengo el array -> ' + graficas)
      const el0 = document.getElementsByClassName('container').item(0)
      el0?.scroll(scrollOptions)
      const el1 = document.getElementsByClassName('container').item(1)
      el1?.scroll(scrollOptions)
      const el2 = document.getElementsByClassName('container').item(2)
      el2?.scroll(scrollOptions)
    } else {
      console.info('lleno el array')
      for (let index = 0; index < document.getElementsByClassName('container').length; index++) {
        graficas.push(document.getElementsByClassName('container')[index])
        document.getElementsByClassName('container')[index].scrollBy(event._vts, 0)
        console.info(document.getElementsByClassName('container')[index])
      }
      graficas.shift()
      console.info('asi queda el array -> ' + graficas)
    }
  }
}  

затем я разделяю часть шаблона, которая отображает диаграмму с полосами прокрутки, которые я хочу переместить:

  <h2>CPU</h2>
    <div class = "container" @scroll = "handleScroll">
      <div class = "containerBody">
        <Bar :data = "cpu" :options = "options" />
      </div>
    </div>
    <h2>IO</h2>
    <div class = "container" @scroll = "handleScroll">
      <div class = "containerBody">
        <Bar :data = "io" :options = "options" />
      </div>
    </div>
    <h2>SEC</h2>
    <div class = "container" @scroll = "handleScroll">
      <div class = "containerBody">
        <Bar :data = "sec" :options = "options" />
      </div>
    </div>

Любая идея, как я могу приблизиться к достижению этого?

Можно ли использовать сторонние библиотеки для этой задачи? Существует плагин Vue, vue-scroll-sync, который может помочь. npmjs.com/package/vue-scroll-sync Даже если вы не можете использовать саму библиотеку, возможно, вы сможете вдохновиться реализацией.

RNanoware 13.04.2023 19:14

@Mayank Есть ли конкретная причина, по которой вы добавили тег [node.js] к этому вопросу? Я не вижу смысла добавлять его, так как JavaScript работает в браузере...

Heretic Monkey 13.04.2023 20:31

Верно, но почти всегда разработка ведется с использованием node.js. Затем он упаковывается и отправляется для запуска в браузере.

Mayank Kumar Chaudhari 14.04.2023 02:34
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Подход 1: вместо событий прокрутки слушайте событие колеса.

В основном пользователи прокручивают страницы жестами или колесиком мыши. При этом вы можете легко избежать бесконечного цикла (один свиток запускает другой и наоборот). Это не будет работать, когда пользователь прокручивает, перетаскивая маркер прокрутки.

Подход 2: прислушивайтесь к наведению курсора мыши, чтобы узнать, какой элемент находится непосредственно под курсором, и используйте только событие прокрутки этого элемента для синхронизации прокрутки.

Ответ принят как подходящий

Следующий фрагмент представляет собой модифицированную/упрощенную версию исходного кода для Vue Scroll Sync. В зависимости от сложности ваших потребностей (и вашей способности использовать сторонние зависимости в вашей кодовой базе), вы можете захотеть получить эту библиотеку напрямую, а не жестко программировать компонент.

Несколько уточнений:

  • Обратите внимание на использование uuid для обозначения различных регионов, положение прокрутки которых должно быть синхронизировано. Это предотвращает «двойной учет» данного события прокрутки при обновлении позиций прокрутки в других регионах.
  • Во всех случаях обработчик onScroll временно удаляется из div при изменении положения прокрутки. Опять же, это предотвращает поведение «двойного счета», которое может повлиять на плавную прокрутку.
  • Элементы div оформлены и окрашены для удобства демонстрации, но, конечно, вы можете скопировать собственную разметку и содержимое в компонент scroll-sync для достижения того же эффекта. Глубокая вложенность элементов DOM по-прежнему должна работать, потому что topNode компонента вычисляется при монтировании, а события отправляются/захватываются на этом узле.

let uuid = 0;

Vue.component('scroll-sync', {
  name: 'ScrollSync',
  template: document.querySelector("#scroll-sync-template").innerHTML,
  data() {
    return {
      topNode: null
    }
  },
  beforeCreate() {
    this.uuid = uuid.toString();
    uuid += 1;
  },
  mounted() {
    let parent = this.$parent
    while (parent) {
      this.topNode = parent
      parent = this.topNode.$parent
    }

    const vue = this;
    this.topNode.$on('scroll-sync', function(data) {
      if (data.emitter === vue.uuid) {
        return
      }
      const {
        scrollTop,
        scrollHeight,
        clientHeight,
        barHeight
      } = data

      const scrollTopOffset = scrollHeight - clientHeight

      vue.$el.onscroll = null
      if (scrollTopOffset > barHeight) {
        vue.$el.scrollTop = scrollTop;
      }
      window.requestAnimationFrame(() => {
        vue.$el.onscroll = vue.handleScroll
      })
    })
    this.$el.onscroll = this.handleScroll
  },
  methods: {
    handleScroll: function(e) {
      const vue = this
      window.requestAnimationFrame(() => {
        const {
          scrollTop,
          scrollHeight,
          clientHeight,
          offsetHeight
        } = e.target

        this.topNode.$emit('scroll-sync', {
          scrollTop,
          scrollHeight,
          clientHeight,
          barHeight: offsetHeight - clientHeight,
          emitter: vue.uuid
        })
      })
    }
  }
});

Vue.config.productionTip = false;

new Vue({
  el: '#app'
});
.scroll-sync-container {
  height: 100%;
  width: 100%;
  position: relative;
  overflow: auto;
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id = "app">
  <div style = "display:flex;">
    <scroll-sync vertical style = "height:500px;width:100px;margin-right:50px;">
      <div style = "width:100px;height:1000px;background:linear-gradient(red, green, blue);"></div>
    </scroll-sync>
    <scroll-sync vertical style = "height:500px;width:100px;">
      <div style = "width:100px;height:2000px;background:linear-gradient(red, green, blue);"></div>
    </scroll-sync>
  </div>
</div>

<div id = "scroll-sync-template">
  <div class = "scroll-sync-container">
    <slot></slot>
  </div>
</div>

Другие вопросы по теме