source

두 디브의 스크롤 위치를 동기화하려면 어떻게 해야 합니까?

ittop 2023. 10. 19. 22:43
반응형

두 디브의 스크롤 위치를 동기화하려면 어떻게 해야 합니까?

나는 특정한 폭(예: 500px)으로 2 div를 가지고 싶습니다.한쪽은 수평으로 정렬되어 있습니다.

상단 박스는 스크롤 바를 숨겨야 하고 하단에는 스크롤 바가 나타나야 하며 사용자가 스크롤 할 때 상단 박스의 오프셋을 하단 박스의 값으로 변경했으면 합니다.아래쪽 DIV가 수평으로 스크롤할 때 위쪽 DIV도 동시에 스크롤하는 것처럼 보입니다.

이것을 Jquery에서 진행하는 것이 더 쉽다면 저는 기쁩니다.

$('#bottom').on('scroll', function () {
    $('#top').scrollTop($(this).scrollTop());
});

사용중입니다..scrollTop()모든 것을 다 바쳐서, 그것을 얻는 것.scrollTop스크롤 바가 있는 요소의 값, 설정scrollTop다른 요소가 스크롤 위치를 동기화하려면: http://api.jquery.com/scrollTop

이것은 당신의 하단 요소가 다음과 같은 ID를 가지고 있다고 가정합니다.bottom그리고 당신의 상위 요소는 다음과 같은 ID를 가지고 있습니다.top.

스크롤 바를 숨길 수 있습니다.topCSS를 사용하는 요소:

#top {
    overflow : hidden;
}

데모: http://jsfiddle.net/sgcer/1884/

이런 일을 할 이유가 전혀 없었던 것 같은데, 실제로 보면 꽤 멋있어 보이네요.

이것이 오래된 실이라는 것을 알지만, 아마도 이것이 누군가에게 도움이 될 것입니다.두 방향으로 스크롤을 동기화해야 하는 경우, 스크롤 이벤트가 주기적으로 진행되고 스크롤이 매끄럽지 않기 때문에 두 컨테이너의 스크롤 이벤트를 모두 처리하고 스크롤 값을 설정하는 것만으로는 충분하지 않습니다(Hightom의 예와 같이 마우스 휠을 사용하여 세로로 스크롤해 보십시오).

스크롤을 이미 동기화하고 있는지 확인할 수 있는 방법의 예는 다음과 같습니다.

var isSyncingLeftScroll = false;
var isSyncingRightScroll = false;
var leftDiv = document.getElementById('left');
var rightDiv = document.getElementById('right');

leftDiv.onscroll = function() {
  if (!isSyncingLeftScroll) {
    isSyncingRightScroll = true;
    rightDiv.scrollTop = this.scrollTop;
  }
  isSyncingLeftScroll = false;
}

rightDiv.onscroll = function() {
  if (!isSyncingRightScroll) {
    isSyncingLeftScroll = true;
    leftDiv.scrollTop = this.scrollTop;
  }
  isSyncingRightScroll = false;
}
.container {
  width: 200px;
  height: 500px;
  overflow-y: auto;
}

.leftContainer {
  float: left;
}

.rightContainer {
  float: right;
}
<div id="left" class="container leftContainer">
Sed ut perspiciatis, unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit, aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui dolorem ipsum, quia dolor sit, amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt, ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla pariatur? At vero eos et accusamus et iusto odio dignissimos ducimus, qui blanditiis praesentium voluptatum deleniti atque corrupti, quos dolores et quas molestias excepturi sint, obcaecati cupiditate non provident, similique sunt in culpa, qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio, cumque nihil impedit, quo minus id, quod maxime placeat, facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet, ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.
</div>
<div id="right" class="container rightContainer">
Sed ut perspiciatis, unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit, aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui dolorem ipsum, quia dolor sit, amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt, ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla pariatur? At vero eos et accusamus et iusto odio dignissimos ducimus, qui blanditiis praesentium voluptatum deleniti atque corrupti, quos dolores et quas molestias excepturi sint, obcaecati cupiditate non provident, similique sunt in culpa, qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio, cumque nihil impedit, quo minus id, quod maxime placeat, facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet, ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.
</div>

음정은 여기 있습니다.

좋아요, 그래서 여기에 제시된 모든 옵션을 평가해봤는데 모두 한 가지 양식의 한계가 있었습니다.

  • 마우스 스크롤 휠을 사용하여 승인된 답변이 알려진 문제로 인해 어려움을 겪습니다.
  • 다음으로 높은 업보팅은 스크롤 휠 문제가 없지만 알려진 두 요소에만 적용됩니다.더 많은 요소가 필요한 경우 확장성이 없습니다.
  • 가능성을 보여주는 유일한 해결책은 라초의 것이었지만, 코드에는 코드 조각에 포함되지 않은 알려진 요소 참조가 있었습니다.긍정적인 측면에서는 성능에 필요한 구조를 가지고 있었고, TypeScript로 되어 있습니다.

이를 활용하여 무제한의 요소로 작동할 수 있는 재사용 가능한 버전을 만들었으며 JQuery가 필요하지 않습니다.

function scrollSync(selector) {
  let active = null;
  document.querySelectorAll(selector).forEach(function(element) {
    element.addEventListener("mouseenter", function(e) {
      active = e.target;
    });

    element.addEventListener("scroll", function(e) {
      if (e.target !== active) return;

      document.querySelectorAll(selector).forEach(function(target) {
        if (active === target) return;

        target.scrollTop = active.scrollTop;
        target.scrollLeft = active.scrollLeft;
      });
    });
  });
}

//RWM: Call the function on the elements you need synced.
scrollSync(".scrollSync");

이에 대한 JSFiddle은 http://jsfiddle.net/gLa2ndur/3 에서 확인할 수 있습니다.가로 스크롤 및 세로 스크롤 예제를 모두 사용하는 것을 확인할 수 있습니다.

알려진 유일한 제한 사항은 크기가 다른 div에서는 작동하지 않을 수 있다는 것입니다.만약 당신의 사용 사례가 필요하다고 생각한다면 누군가가 앤드류의 작업을 여기에 포함시키는 작업을 할 수 있을 것이라고 확신합니다(내 작업은 그렇지 않습니다).

저는 이것이 누군가에게 도움이 되기를 바랍니다!

저는 이중 방향 솔루션을 찾고 있었는데 여러분들 덕분에 이렇게 할 수 있었습니다.

$('#cells').on('scroll', function () {
$('#hours').scrollTop($(this).scrollTop());
$('#days').scrollLeft($(this).scrollLeft());});

JSFiddle: https://jsfiddle.net/sgcer/1274/ 에서 참조하십시오.

언젠가 누군가에게 도움이 되길 바라요 :-)

이러한 루프 문제를 방지하고 부드러운 스크롤을 달성하는 또 다른 솔루션.이렇게 하면 초점이 맞는 요소만 스크롤 이벤트를 얻을 수 있습니다.

let activePre: HTMLPreElement = null;
document.querySelectorAll(".scrollable-pre").forEach(function(pre: HTMLPreElement) {
    pre.addEventListener("mouseenter", function(e: MouseEvent) {
        let pre = e.target as HTMLPreElement;
        activePre = pre;
    });

    pre.addEventListener("scroll", function(e: MouseEvent) {
        let pre = e.target as HTMLPreElement;

        if (activePre !== pre) {
            return;
        }

        if (pre !== versionBasePre) {
            versionBasePre.scrollTop = pre.scrollTop;
            versionBasePre.scrollLeft = pre.scrollLeft;
        }

        if (pre !== versionCurrentPre) {
            versionCurrentPre.scrollTop = pre.scrollTop;
            versionCurrentPre.scrollLeft = pre.scrollLeft;
        }

    });
});

위의 답변 덕분에 저에게 우선적으로 도움이 되는 혼합 솔루션을 만들었습니다.

var isLeftScrollTopCalled = false;
$('#leftElement').scroll(function (e) {
    if (isRightScrollTopCalled) {
        return isRightScrollTopCalled = false;
    }

    $('#rightElement').scrollTop($(this).scrollTop());
    isLeftScrollTopCalled = true;
});

var isRightScrollTopCalled = false;
$('#rightElement').scroll(function (e) {
    if (isLeftScrollTopCalled) {
        return isLeftScrollTopCalled = false;
    }

    $('#leftElement').scrollTop($(this).scrollTop());
    isRightScrollTopCalled = true;
});

저는 그의 질문이 꽤 오래되었다는 것을 알았지만 타이머를 사용하는 것보다 훨씬 더 효과적인 jQuery 구현을 남길 수 있을 것이라고 생각했습니다.여기서는 이전에 사용한 솔루션과 같이 두 개의 이벤트 리스너를 사용하고 있지만, 이는 두 개의 다른 크기의 디바 상자에 대한 스크롤을 동기화하기 위해 비율/%를 사용합니다.이와 같은 지식을 적용하여 스크롤 바의 위치를 바닐라 JS 솔루션에 적용할 수 있습니다.이렇게 하면 두 디브 사이의 스크롤이 훨씬 더 부드러워집니다.

/** Scroll sync between editor and preview **/
// Locks so that only one pane is in control of scroll sync
var eScroll = false;
var pScroll = false;
// Set the listener to scroll
this.edit.on('scroll', function() {
    if(eScroll) { // Lock the editor pane
        eScroll = false;
        return;
    }
    pScroll = true; // Enable the preview scroll

    // Set elements to variables
    let current = self.edit.get(0);
    let other = self.preview.get(0);

    // Calculate the position of scroll position based on percentage
    let percentage = current.scrollTop / (current.scrollHeight - current.offsetHeight);

    // Set the scroll position on the other pane
    other.scrollTop = percentage * (other.scrollHeight - other.offsetHeight);
});
this.preview.on('scroll', function() {
    if(pScroll) { // Lock the preview pane
        pScroll = false;
        return;
    }
    eScroll = true; // Enable the editor scroll

    // Set elements to variables
    let current = self.preview.get(0);
    let other = self.edit.get(0);

    // Calculate the position of scroll position based on percentage
    let percentage = current.scrollTop / (current.scrollHeight - current.offsetHeight);

    // Set the scroll position on the other pane
    other.scrollTop = percentage * (other.scrollHeight - other.offsetHeight);

});

DOM 조작으로 두가지 기능을 추가하였습니다.

function scrollSynchronizeY(element1,element2){
  document.querySelector(element1).addEventListener('scroll',function(e){
    document.querySelector(element2).scrollTop = e.target.scrollTop;
  })
  document.querySelector(element2).addEventListener('scroll',function(e){
    document.querySelector(element1).scrollTop = e.target.scrollTop;
  })
}
function scrollSynchronizeX(element1,element2){
  document.querySelector(element1).addEventListener('scroll',function(e){
    console.log('scrolled left ',e.target.scrollLeft);
    document.querySelector(element2).scrollLeft = e.target.scrollLeft;
  })
  document.querySelector(element2).addEventListener('scroll',function(e){
    document.querySelector(element1).scrollLeft = e.target.scrollLeft;
  })
}

언급URL : https://stackoverflow.com/questions/9236314/how-do-i-synchronize-the-scroll-position-of-two-divs

반응형