jjzjj

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

coder 2023-12-04 原文

Setting scrollLeft does reset the scroll bar positionupdating the content works as expected但是当doing both at the same time滚动条变得困惑并且不会重置。

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

请注意,在笔记本电脑上,该元素会无限滚动,而在安卓设备上,该元素只会滚动到达到初始设置的“最大滚动”为止

应该发生什么:

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

以下是我解决问题的尝试

  1. .inner 上设置 transform: translateX(0px) see here其行为比以前更糟。

  2. 列出的修复 here这是针对 android 中的一个先前错误,其中设置 scrollLeft 根本不起作用。这对解决问题根本没有帮助。

  3. wrap.appendChild(inner) 在每个滚动事件上,这减慢了向下滚动但没有解决问题,因为 chrome 会记住滚动位置。即使我可以让 chrome 忘记滚动位置,这也是一个 hack(这看起来似乎有道理,但又是另一个 hack)

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

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;
};
*, *::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;
}
<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>

最佳答案

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

( Demo )

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);
};

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

关于javascript - Android 在滚动事件更新内容时设置 scrollLeft 不更新滚动条位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30144841/

有关javascript - Android 在滚动事件更新内容时设置 scrollLeft 不更新滚动条位置的更多相关文章

  1. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  2. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  3. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  4. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  5. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  6. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

  7. ruby - 正则表达式在哪个位置失败? - 2

    我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束

  8. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  9. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  10. ruby-on-rails - 事件管理员和自定义方法 - 2

    这是我在ActiveAdmin中的自定义页面ActiveAdmin.register_page"Settings"doaction_itemdolink_to('Importprojects','settings/importprojects')endcontentdopara"Text"endcontrollerdodefimportprojectssystem"rakedataspider:import_projects_ninja"para"OK"endendend我想做的是,当我单击“导入项目”按钮时,我想在Controller中执行rake任务。但是我无法访问该方法。可能是什

随机推荐