我正在尝试同步两个可滚动的 DIVS 滚动位置。
遵循的方法:
Method - 1 : on-scroll事件设置其他DIV的scrollTop。 问题:滚动事件最后执行,UI 在 iOS Safari 中缓慢。
Method - 2 :使用 setInterval 来同步两个滚动位置。 问题:iOS 在滚动期间不执行定时器功能, 所以滚动位置在最后同步。同样,这更加缓慢。 尝试过,许多博客中提到的计时器已修复,但仍然没有优雅。
Method -3 :尝试自定义滚动条,所以 iScroll 并尝试在 scroll 事件上同步两者,
问题:这看起来好多了,但在 iOS 中仍然很慢!!!
Method -4 :尝试自定义滚动条,所以 iScroll 并尝试在 scroll 事件上同步两者,
问题:使用 iScroll 但使用定时器而不是依赖于 onScroll 事件,
但是在touchmove期间,iOS忙于提供动画
而是执行所需的计时器直到触摸结束。
下面的代码引用了这个方法。它也很迟钝。
var active = .., other = ...
// active : active Scrolling element
// other : Element to be in sync with active
window.setInterval(function () {
var y;
if (active) {
y = active.y;
} else {
return;
}
var percentage = -y / (active.scrollerHeight - active.wrapperHeight);
var oscrollTop = percentage * (other.scrollerHeight - other.wrapperHeight);
if (-other.maxScrollY >= toInt(oscrollTop)) {
other.scrollTo(0, -toInt(oscrollTop));
}
}, 20);
如何使两个可滚动 DIVS 的同步滚动位置更顺畅。请给我一些建议,这让我很恼火。
最佳答案
依靠滚动事件(OPs 方法 1) 适合桌面实现。滚动事件在屏幕更新之前触发。在移动设备上,尤其是 iOS,情况并非如此。由于资源有限,滚动事件仅在用户完成(抬起手指)滚动操作后触发。
当用户在 iOS 上滚动时产生滚动事件需要手动实现滚动。
注册 touchstart 事件。并获得第一次接触:
var element1 = document.getElementById('content1');
var element2 = document.getElementById('content2');
var activeTouch = null;
var touchStartY = 0;
var element1StartScrollTop = 0;
var element2scrollSyncFactor = 0;
document.addEventListener('touchstart', function(event) {
event.preventDefault();
var touch = event.changedTouches[0];
if ( activeTouch == null ) {
// implement check if touch started on an element you want to be scrollable
// save a reference to the scrolling element for the other functions
activeTouch = touch;
touchStartY = touch.screenY;
// if scroll content does not change do this calculation only once to safe compute and dom access time while animating
calcSyncFactor();
}
});
function calcSyncFactor()
{
// calculate a factor for scroll areas with different height
element2scrollSyncFactor = (element2.scrollHeight - element2.clientHeight) / (element1.scrollHeight - element1.clientHeight);
}
根据手指移动更新滚动位置:
document.addEventListener('touchmove', function() {
for ( var i = 0; i < event.changedTouches.length; i++ ) {
var touch = event.changedTouches[i];
if ( touch === activeTouch ) {
var yOffset = touch.screenY - touchStartY;
element1.scrollTop = element1StartScrollTop + (0 - yOffset);
syncScroll();
break;
}
}
});
function syncScroll()
{
element2.scrollTop = Math.round(element1.scrollTop * element2scrollSyncFactor);
}
可以添加一个仅在用户将手指移动了一些像素后才开始滚动的检查。这样,如果用户单击某个元素,文档将不会滚动一些像素。
用户抬起手指后的清理:
document.addEventListener('touchend', touchEnd);
document.addEventListener('touchcancel', touchEnd);
function touchEnd(event)
{
for ( var i = 0; i < event.changedTouches.length; i++ ) {
var touch = event.changedTouches[i];
if ( touch === activeTouch ) {
// calculate inertia and apply animation
activeTouch = null;
break;
}
}
}
要使滚动感觉更自然,请应用 iOS 橡皮筋效果和惯性。通过将最后一个 touchMove yOffset 与之前的比较来计算滚动速度。从这个速度应用一个动画(例如 css 过渡)来慢慢停止滚动
参见 FIDDLE .见result on iOS . fiddle 只实现了触摸设备的解决方案。对于桌面设备,使用 OP 的方法 1. 实现一个条件,检查根据设备使用哪种方法。
可以使用 requestAnimationFrame 在 javascript 中制作动画。在移动设备上可能更高效的方法是使用 css 转换或 css 动画。虽然元素滚动位置不能用 css 动画。
将 html 的结构更改为。
div:溢出:隐藏
div:position: absolute
根据内容大小,在内容 div 上使用 css 属性 -webkit-transform: translateZ(0)。这将创建一个具有自己的背衬表面的新层,该层将在 gpu 上合成。
实现上述函数,以便它们为内容的 top 位置而不是 scrollTop 设置动画
var element1 = document.getElementById('content1');
var element2 = document.getElementById('content2');
var activeTouch = null;
var touchStartY = 0;
var element1StartScrollTop = 0;
var element2scrollSyncFactor = 0;
var offsetY = 0;
var lastOffsetY = 0;
document.addEventListener('touchstart', function(event) {
event.preventDefault();
var touch = event.changedTouches[0];
if ( activeTouch == null ) {
activeTouch = touch;
touchStartY = touch.screenY;
// use offsetTop instead of scrollTop
element1StartScrollTop = element1.offsetTop;
// if scroll content does not change do this calculation only once to safe compute time while animating
calcSyncFactor();
// cancel inertia animations
element1.style.webkitTransition = 'none';
element2.style.webkitTransition = 'none';
}
});
function calcSyncFactor()
{
// calculate a factor for scroll areas with different height
// use the div's sizes instead of scrollTop
element2scrollSyncFactor = (element2.clientHeight - element2.parentNode.clientHeight) / (element1.clientHeight - element1.parentNode.clientHeight);
}
document.addEventListener('touchmove', function() {
for ( var i = 0; i < event.changedTouches.length; i++ ) {
var touch = event.changedTouches[i];
if ( touch === activeTouch ) {
lastOffsetY = offsetY;
offsetY = touch.screenY - touchStartY;
// use offsetTop instead of scrollTop
element1.style.top = (element1StartScrollTop + offsetY) + 'px';
syncScroll();
break;
}
}
});
function syncScroll()
{
element2.style.top = Math.round(element1.offsetTop * element2scrollSyncFactor) + 'px';
}
document.addEventListener('touchend', touchEnd);
document.addEventListener('touchcancel', touchEnd);
function touchEnd(event)
{
for ( var i = 0; i < event.changedTouches.length; i++ ) {
var touch = event.changedTouches[i];
if ( touch === activeTouch ) {
applyInertia();
activeTouch = null;
break;
}
}
}
当用户完成滚动并抬起手指时应用惯性
function applyInertia()
{
var velocity = offsetY - lastOffsetY;
var time = Math.abs(velocity) / 150;
var element1EndPosition = element1.offsetTop + velocity;
element1.style.webkitTransition = 'top ' + time + 's ease-out';
element1.style.top = element1EndPosition + 'px';
element2.style.webkitTransition = 'top ' + time + 's ease-out';
element2.style.top = Math.round(element1EndPosition * element2scrollSyncFactor) + 'px';
}
惯性是根据用户抬起手指时的速度计算得出的。 摆弄这些值以获得所需的结果。橡皮筋效果也可以在此函数中实现。没有 javascript 涉及应用 css 动画可能是诀窍。另一种方法是为转换完成时注册事件。如果过渡完成并且滚动位置在容器外部,则应用一个新的过渡来动画内容。
参见 FIDDLE .见result on iOS .
关于javascript - 如何使同步两个 Divs 滚动位置更平滑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25477651/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
我有一大串格式化数据(例如JSON),我想使用Psychinruby同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解