在滚动事件上更新内容时Android设置scrollLeft不会更新滚动条位置

6 javascript android scroll google-chrome touch

设置scrollLeft会重置滚动条位置更新内容按预期工作但在同时执行这两项操作时滚动条会混淆并且不会重置.

要查看预期行为与意外行为,请在具有触摸板的设备上查看每个演示,并使用触摸板在包装器内向左或向右滚动,然后尝试在Android设备上执行相同操作.

请注意,在笔记本电脑上元素将无限滚动,在Android设备上元素将仅滚动直到它达到最初设置的"最大滚动"

会发生什么:

当用户向左或向右滚动时,将第一个子元素移动到nodeList的末尾或将最后一个子元素移动到开头,并将滚动位置重置为第一个子元素的一半.

以下是我解决问题的尝试

  1. 设置transform: translateX(0px).inner 这里看到其中有比以前更糟的行为.

  2. 这里列出的修复程序是针对android中的先前错误,其中设置scrollLeft根本不起作用.这根本没有帮助.

  3. wrap.appendChild(inner)在每个滚动事件,这减慢了向下滚动,但没有解决问题因为chrome记住滚动位置.这将是一个黑客,即使我可以得到铬忘记滚动位置(看起来它可能是合理的,但将是另一个黑客)

我意识到我可以嗅探浏览器并恢复到jquery ui移动刷卡设置,但我认为如果我可以让它工作,我就不必使用外部库来模拟本机行为(并且本机总是更好).

var log = function(event) {
  var log = document.querySelector('.log');
  log.innerHTML = event + "<br>" + log.innerHTML;
};
var wrap = document.querySelector('.wrap');
var inner = document.querySelector('.inner');
var items = document.querySelectorAll('.item');
var controlLeft = document.createElement('a');
controlLeft.className = 'control control-left';
controlLeft.href = 'javascript:void(0)';
controlLeft.innerHTML = '&lt;';
controlLeft.onclick = function() {
  log('click left');
  inner.scrollLeft++;
};
wrap.appendChild(controlLeft);
var controlRight = document.createElement('a');
controlRight.className = 'control control-right';
controlRight.href = 'javascript:void(0)';
controlRight.innerHTML = '&gt;';
controlRight.onclick = function() {
  log('click right');
  inner.scrollLeft--;
};
wrap.appendChild(controlRight);
var darken1 = document.createElement('div');
var darken2 = document.createElement('div');
darken1.className = 'darken';
darken2.className = 'darken';
items[0].appendChild(darken1);
items[2].appendChild(darken2);
var getWidth = function(element) {
  return Number(window.getComputedStyle(element, null).getPropertyValue('width').replace('px', '')) + 1;
};
wrap.style.overflow = 'hidden';
inner.style.overflowY = 'hidden';
inner.style.overflowX = 'auto';
wrap.style.height = inner.scrollHeight + 'px';
window.onresize = function() {
  wrap.style.height = inner.scrollHeight + 'px';
  inner.scrollLeft = 0;
  inner.scrollLeft = getWidth(items[0]) / 2;
};
inner.scrollLeft = getWidth(items[0]) / 2;
oldScroll = inner.scrollLeft;
inner.onscroll = function() {
  if (inner.scrollLeft < oldScroll) {
    log('scroll right');
    inner.appendChild(inner.querySelector('.item:first-child'));
    inner.querySelector('.item:first-child').appendChild(darken1);
    inner.querySelector('.item:nth-child(3)').appendChild(darken2);
  } else if (inner.scrollLeft > oldScroll) {
    log('scroll left');
    var first = inner.querySelector('.item:first-child');
    var last = inner.querySelector('.item:last-child');
    inner.insertBefore(last, first);
    inner.querySelector('.item:first-child').appendChild(darken1);
    inner.querySelector('.item:nth-child(3)').appendChild(darken2);
  }
  inner.scrollLeft = 0;
  inner.scrollLeft = getWidth(items[0]) / 2;
  oldScroll = inner.scrollLeft;
};
Run Code Online (Sandbox Code Playgroud)
*, *::before, *::after {
  box-sizing: border-box;
}
html,
body {
  padding: 0;
  margin: 0;
  max-height: 100%;
  overflow: hidden;
}
.wrap {
  position: relative;
}
.control {
  font-weight: bold;
  text-decoration: none;
  display: inline-block;
  position: absolute;
  padding: 10px;
  background: rgba(255, 255, 255, 0.5);
  top: 50%;
  transform: translateY(-50%);
  color: #FFF;
  font-size: 20pt;
}
.control-left {
  padding-right: 20px;
  border-top-right-radius: 50%;
  border-bottom-right-radius: 50%;
  left: 0;
}
.control-right {
  padding-left: 20px;
  border-top-left-radius: 50%;
  border-bottom-left-radius: 50%;
  right: 0;
}
.inner {
  font-size: 0;
  white-space: nowrap;
  overflow: auto;
}
.item {
  position: relative;
  display: inline-block;
  font-size: 1rem;
  white-space: initial;
  padding-bottom: 33.3333%;
  width: 50%;
}
.item .darken {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.8);
}
.item[data-n="2"] {
  background-image: url(http://www.lorempixel.com/400/300/animals);
  background-size: cover;
}
.item[data-n="3"] {
  background-image: url(http://www.lorempixel.com/400/300/business);
  background-size: cover;
}
.item[data-n="4"] {
  background-image: url(http://www.lorempixel.com/400/300/cats);
  background-size: cover;
}
.item[data-n="5"] {
  background-image: url(http://www.lorempixel.com/400/300/city);
  background-size: cover;
}
.item[data-n="6"] {
  background-image: url(http://www.lorempixel.com/400/300/food);
  background-size: cover;
}
.item[data-n="7"] {
  background-image: url(http://www.lorempixel.com/400/300/nightlife);
  background-size: cover;
}
.item[data-n="8"] {
  background-image: url(http://www.lorempixel.com/400/300/fashion);
  background-size: cover;
}
.item[data-n="9"] {
  background-image: url(http://www.lorempixel.com/400/300/people);
  background-size: cover;
}
.item[data-n="10"] {
  background-image: url(http://www.lorempixel.com/400/300/nature);
  background-size: cover;
}
.item[data-n="11"] {
  background-image: url(http://www.lorempixel.com/400/300/sports);
  background-size: cover;
}
.item[data-n="12"] {
  background-image: url(http://www.lorempixel.com/400/300/technics);
  background-size: cover;
}
.item[data-n="13"] {
  background-image: url(http://www.lorempixel.com/400/300/transport);
  background-size: cover;
}
Run Code Online (Sandbox Code Playgroud)
<div class="wrap">
  <div class="inner">
    <div class="item" data-n="2"></div>
    <div class="item" data-n="3"></div>
    <div class="item" data-n="4"></div>
    <div class="item" data-n="5"></div>
    <div class="item" data-n="6"></div>
    <div class="item" data-n="7"></div>
    <div class="item" data-n="8"></div>
    <div class="item" data-n="9"></div>
    <div class="item" data-n="10"></div>
    <div class="item" data-n="11"></div>
    <div class="item" data-n="12"></div>
    <div class="item" data-n="13"></div>
  </div>
</div>
<div class="log">
</div>
Run Code Online (Sandbox Code Playgroud)

小智 1

为了暂时解决这个问题,我将该函数封装在超时中。超时可以短至 1 毫秒。我不知道为什么,但更改内容并在滚动的确切事件上设置scrollLeft 会导致浏览器不重置滚动条。

演示

inner.onscroll = function() {
  window.clearTimeout(window.updateTimeout);
  window.updateTimeout = window.setTimeout(function() {
    if (inner.scrollLeft < oldScroll) {
      log('scroll right');
      inner.appendChild(inner.querySelector('.item:first-child'));
    } else if (inner.scrollLeft > oldScroll) {
      log('scroll left')
      var first = inner.querySelector('.item:first-child');
      var last = inner.querySelector('.item:last-child');
      inner.insertBefore(last, first);
    }
    inner.querySelector('.item:first-child').appendChild(darken1);
    inner.querySelector('.item:nth-child(3)').appendChild(darken2);
    inner.scrollLeft = 0;
    inner.scrollLeft = getWidth(items[0]) / 2;
    oldScroll = inner.scrollLeft;
  }, 1);
};
Run Code Online (Sandbox Code Playgroud)

虽然这确实“解决”了问题,但我认为这是一种黑客行为。我将这个问题悬而未决,看看是否能得到真正的答案。