简体   繁体   中英

Laggy element position update on mobile scrolling

I'm trying to make a sticky header + first column table. Works fine on desktop browsers.

However, when I scroll the table's x-axis on a mobile device, the position update is dragging ie not fast enough.

I've read various SO-threads that suggest iScroll . I'm not really sure how to use it appropriately in this case. Should intercept the tbody scroll event, perevent the default behaviour and update the position based on iScroll's event values? Please point me in the right direction here :)

$(function() {
  var $tbody = $('tbody');

  $tbody.on('scroll', function(e) { 
    var left = $tbody.scrollLeft();
    $('thead').css('left', -left); 
    $('tbody td:nth-child(1), thead th:nth-child(1)').css('left', left);
  });

  var iScroll = new IScroll($tbody[0], { probeType: 3 });
  iScroll.on('scroll', function(){
    console.log('not fired?');
  });
});

https://jsfiddle.net/97r799gr/

To reproduce the problem, it's probably easiest for you to visit https://jsfiddle.net/97r799gr/show on your mobile. I'm using an SGS7 edge so I think this will be reproducible on pretty much any mobile device.

IScroll uses a wrapper with fixed dimensions with one scrollable content in it. Therefore we can't use tbody as a wrapper. We should wrap the whole table and hold desired elements with CSS when scrolling.

I've created a fiddle with iscroll-probe.js code in it ( iscroll.js hasn't got a scroll event). Bad news is that it works only on my iPhone. Scrolling is suddenly stops when scrolling it on my android5.1 device.

// main code
$(document).ready(function(){ 
  $('#pos').text('initialize iscroll');
  try{
    var iScroll = new IScroll('#wrapper', { 
      interactiveScrollbars: true, 
      scrollbars: true, 
      scrollX: true, 
      probeType: 3, 
      useTransition:false, 
      bounce:false
    });
  } catch(e) {
    $('#error').text('Error ' + e.name + ":" + e.message + "\n" + e.stack);
  }

  $('#pos').text('initialized');

  iScroll.on('scroll', function(){
    var pos = $('#scroller').position();
    $('#pos').text('pos.left=' + pos.left + ' pos.top=' + pos.top);

    // code to hold first row and first column
    $('#scroller th:nth-child(1)').css({top: (-pos.top), left: (-pos.left), position:'relative'});
    $('#scroller th:nth-child(n+1)').css({top: (-pos.top), position:'relative'});

    $('#scroller td:nth-child(1)').css({left: (-pos.left), position:'relative'});
  });
});

https://jsfiddle.net/0qv1kjac/11/

I wasn't able to make it work with pure CSS, so I decided to remove iScroll and rewrite the javascript in vanilla js. It works fine on my iphone now. I don't have an android to test with.

New fiddle: https://jsfiddle.net/66a1b2rw/

Everything is the same as your original fiddle except the js:

updated js

var tbody = document.querySelector('tbody');
var thead = document.querySelector('thead');
var firstCol = document.querySelectorAll('tbody td:nth-child(1), thead th:nth-child(1)');
console.log(firstCol);
tbody.addEventListener('scroll', function() {
    var left = tbody.scrollLeft;
  thead.style.left = '-' + left + 'px';
  firstCol.forEach(function(x) {x.style.left = left + 'px'})
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM