7

--> Please goto Edit part of this Question

I want to synchronise scroll bar of two divs and this is how I am doing it

 var div1 = document.getElementById('element1'),
    div2 = document.getElementById('element2');

div1.addEventListener('touchmove', scrolled, false);
div2.addEventListener('touchmove', scrolled, false);

function getscrollTop(node) {
    return node.pageYOffset || node.scrollTop;
}

function scrolled() {

    var node = this, scrollTop = getscrollTop(node);

    var percentage = scrollTop / (node.scrollHeight - node.clientHeight);

    var other = document.getElementById({
        "element1": "element2",
        "element2": "element1"
    }[node.id]);

    other.scrollTop = percentage * (other.scrollHeight - other.clientHeight);

};

Fiddle -> used scroll instead touchmove

But the problem is it is flickering in low end devices and would like to make it smooth in event low end devices.

Edit

I have used below code to smoothen the scrolling

var children = document.querySelectorAll('.scrolldiv');

var getscrollTop = function(node) {
   return node.pageYOffset || node.scrollTop;
}, toInt = function(n) {
   return Math.round(Number(n));
};

window.setInterval(function() {
  var scrollTop = getscrollTop(children[0]);
  var percentage = scrollTop / (children[0].scrollHeight - children[0].clientHeight);
  var oscrollTop = percentage * (children[1].scrollHeight - children[1].clientHeight);
  // console.log(1);
  children[1].scrollTop = toInt(oscrollTop);
}, 2);

It is smoother in Desktop browsers but in iOS browser, when setting second DIv's scroll it is jerking, jerking in the sense setting scrollTop once scrolling is completed, not while scrolling.

redV
  • 684
  • 1
  • 9
  • 26
Exception
  • 8,111
  • 22
  • 85
  • 136
  • maybe this will help you http://stackoverflow.com/questions/17722497/scroll-smoothly-to-specific-element-on-page – lordkain Jul 24 '14 at 11:36
  • One thing I noticed is on line 17, you are calling a function "getscrollTop(node)" that you already have as a variable scrollTop. Also, you declare "oscrollTop" as a variable and then directly assign it to an object at the very end of your function...just directly assign it to the object. If you're worried about performance on low end devices, code optimization is extremely important. – Michael Jul 24 '14 at 11:37
  • @lordkain What could be the best solution out of them. First solution seems to be doing big calculations in code. – Exception Jul 24 '14 at 11:46

2 Answers2

5

If you round your scroll value numbers to integers then this problem goes away :

http://jsfiddle.net/2Cj4S/15/

I just used a rounding function :

function toInt(n){ return Math.round(Number(n)); };

and this seems to have fixed it. Double values really confused GUI widgets like scrollbars, and 2D drawing.

Oliver Watkins
  • 12,575
  • 33
  • 119
  • 225
  • Thanks for the suggestion. But I just removed scroll handler and used setInterval with 20 seconds to synchronise scroll positions of both the DIVs and it is pretty smooth now. Edit : And also I added your suggestion :) May I know more about what is the reason behind rounding integers? – Exception Jul 24 '14 at 20:45
  • I think it has something to do with internal rounding of the scroll component. I am not sure myself. Also if you reduce the events (like you did) that is a way of not overwhelming the component. – Oliver Watkins Jul 25 '14 at 07:36
4

I don't see why you have to calculate a new percentage here, value which you hand over to the second scroll.. that's probably the reason for the jerking.. instead you could simply take the scroll value from the first scroll and assign it directly to the other scroll.. This will remove the jerky-ness in the other scroll.. and synchronising them..

I just added the following line to the bottom of your scrolled function.. other.scrollTop = getscrollTop(node);

The modified function:-

function scrolled() {

var node = this,
    scrollTop = getscrollTop(node);

var id = node.id;

var percentage = getscrollTop(node) / (node.scrollHeight - node.clientHeight);

var other = document.getElementById({
    "element1": "element2",
    "element2": "element1"
}[id]);

var oscrollTop = percentage * (other.scrollHeight - other.clientHeight)

//other.scrollTop = oscrollTop;
//Please note that I have commented out the above line.. and added the following line
other.scrollTop = getscrollTop(node);

};

I hope this the behaviour you were hoping for, i tested it out on jsfiddle, both scrolls are well synchronised.

Lakmal Caldera
  • 1,001
  • 2
  • 12
  • 25
  • Your solution fails if both elements have different scroll heights – redV Aug 28 '14 at 12:27
  • Hi @redV, I believe the scroll height value is taken relative to its scroll and as this value is passed to the other scroll it makes it look like the the value is in fact taken from the other scroll, so regardless of height, each scroll will scroll the same height based on that value it is passed.. thus it will still synchronise the two scrolls. – Lakmal Caldera Aug 28 '14 at 12:43
  • Yes, you are right. I think no need to calculate percentage :) – redV Aug 28 '14 at 13:37