Javascript 视差滚动问题 - 在 webkit 浏览器中滚动时 div 元素抖动
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13440577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
parallax scrolling issue - div element jerking when scrolling in webkit browsers
提问by NewBoy
I have created a parallax scroll, which seem to be working fine in firefox however in the chrome browser there's a slight jump on the body text when scrolling. click here scroll to the about section. I am not sure if t this is a css or JS issue.. below is a snippet i have incorporated into my parallax function
我创建了一个视差滚动,它在 Firefox 中似乎运行良好,但是在 chrome 浏览器中滚动时正文有轻微的跳跃。单击此处滚动到关于部分。我不确定这是 css 还是 JS 问题.. 下面是我已合并到我的视差函数中的片段
Does anyone know how i an fix this issue?
有谁知道我如何解决这个问题?
$(document).ready(function(){
// Cache the Window object
$window = $(window);
// Cache the Y offset and the speed of each sprite
$('[data-type]').each(function() {
$(this).data('offsetY', parseInt($(this).attr('data-offsetY')));
$(this).data('Xposition', $(this).attr('data-Xposition'));
$(this).data('speed', $(this).attr('data-speed'));
});
// For each element that has a data-type attribute
$('[data-type="background"]').each(function(){
// Store some variables based on where we are
var $self = $(this),
offsetCoords = $self.offset(),
topOffset = offsetCoords.top;
// When the window is scrolled...
$(window).scroll(function() {
// If this section is in view
if ( ($window.scrollTop() + $window.height()) > (topOffset) &&
( (topOffset + $self.height()) > $window.scrollTop() ) ) {
// Scroll the background at var speed
// the yPos is a negative value because we're scrolling it UP!
var yPos = -($window.scrollTop() / $self.data('speed'));
// If this element has a Y offset then add it on
if ($self.data('offsetY')) {
yPos += $self.data('offsetY');
}
// Put together our final background position
var coords = '50% '+ yPos + 'px';
// Move the background
$self.css({ backgroundPosition: coords });
$('[data-type="scroll-text"]', $self).each(function() {
var $text= $(this);
var pos = ($window.scrollTop()/10) * $text.data('speed');
var curP = $text.css('margin-top');
var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
if(is_chrome) {
$text.animate({
paddingTop: pos,
}, 200, 'linear', function() {
// Animation complete.
});
} else {
$text.css('padding-top', pos);
}
});
}; // in view
}); // window scroll
}); // each data-type
}); // document ready
回答by jedd.ahyoung
Some suggestions:
一些建议:
1.) Use position: fixedto avoid any jitter, as you'll be taking the element out of the document flow. You can then position it using z-index.
1.)position: fixed用于避免任何抖动,因为您将从文档流中取出元素。然后您可以使用 z-index 定位它。
2.) Cache as much as you can to ease processing time.
2.) 尽可能多地缓存以减少处理时间。
3.) Math.round may not be necessary, but try adding this CSS to your moving areas: -webkit-transform: translate3d(0,0,0);This will force hardware acceleration in Chrome, which may ease some of the jittering. (It looked smoother on my screen when I added this with Inspector, but it didn't get rid of the jumpiness with the scroll wheel.) Note: Don't do this on your entire document (e.g. body tag), as it might cause some issues with your current layout. (Your navigation bar didn't stick to the top of the window, for instance.)
3.) Math.round 可能不是必需的,但尝试将此 CSS 添加到您的移动区域:-webkit-transform: translate3d(0,0,0);这将强制 Chrome 中的硬件加速,这可能会缓解一些抖动。(当我用 Inspector 添加它时,它在我的屏幕上看起来更平滑,但它并没有摆脱滚轮的跳跃。)注意:不要在整个文档(例如正文标签)上这样做,因为它可能导致您当前的布局出现一些问题。(例如,您的导航栏没有贴在窗口顶部。)
4.) If you have any animations running as part of your parallax logic (tweening the margin into place or something along those lines), remove it - that would probably cause the jump you see.
4.) 如果您有任何动画作为视差逻辑的一部分运行(将边距调整到位或沿这些线进行某些操作),请将其删除 - 这可能会导致您看到的跳跃。
Hope this helps. Best of luck.
希望这可以帮助。祝你好运。
回答by Dawson
I see the same jittering in FireFox and Chrome (Mac). Looking at your containers, one thing that's glaring at me is the pixel position that's being calculated/used.
我在 FireFox 和 Chrome (Mac) 中看到了同样的抖动。看着你的容器,让我眼前一亮的一件事是正在计算/使用的像素位置。
Chrome: <div id="about-title" style="margin-top: 1562.3999999999999px;">
FireFox: <div id="about-title" style="margin-top: 1562.4px;">
Browsers aren't going to allow content to sit at 1/2 pixel, let alone 0.3999999 of a pixel. I think it's moving it, and trying to calculate whether to round up or round down. It jitters because it's calculating with every click of your mouse wheel.
浏览器不会允许内容位于 1/2 像素,更不用说 0.3999999 像素了。我认为它正在移动它,并试图计算是向上取整还是向下取整。它会抖动,因为它会随着鼠标滚轮的每次点击进行计算。
Thus, I'd try adding Math.round() to your positions so that the containers are never being left in limbo.
因此,我会尝试将 Math.round() 添加到您的位置,以便容器永远不会陷入困境。
Take a look at the code here: http://webdesigntutsplus.s3.amazonaws.com/tuts/338_parallax/src/index.html
看看这里的代码:http: //webdesigntutsplus.s3.amazonaws.com/tuts/338_parallax/src/index.html
Firebug some of the elements, and you'll see that their only fraction of a pixel is '0.5'. Most of them (the bulk) go to round number values.
Firebug 一些元素,你会看到它们的像素的唯一分数是“0.5”。他们中的大多数(大部分)去整数值。
回答by alemangui
Have you tried adding the preventdefault inside the scroll function?
您是否尝试在滚动功能中添加 preventdefault ?
$(window).scroll(function(e) {
e.preventDefault();
// rest of your code
}
回答by Patrick548
You are going to have to change the way that the scrolling works (i.e. change how the spacing is computed), but this can be fixed by adding the position:fixedCSS element to the page elements that are scrolling. The problem is coming from the time that it takes for the JavaScript to process and then render.
您将不得不更改滚动的工作方式(即更改间距的计算方式),但这可以通过将position:fixedCSS 元素添加到正在滚动的页面元素来解决。问题来自 JavaScript 处理和渲染所需的时间。
For example, on your page you would set each of the <div>tags containing text to have a fixed position and then use the JavaScript/JQuery function to update the top:CSS element. This should make the page scroll smoothly.
例如,在您的页面上,您可以将<div>包含文本的每个标签设置为具有固定位置,然后使用 JavaScript/JQuery 函数更新top:CSS 元素。这应该使页面平滑滚动。
回答by Louis Ricci
In a previous question I created a fairly good parallax scrolling implementation. Jquery Parallax Scrolling effect - Multi directionalYou might find it useful.
在上一个问题中,我创建了一个相当不错的视差滚动实现。Jquery 视差滚动效果 - 多向您可能会发现它很有用。
Here's the JSFiddle http://jsfiddle.net/9R4hZ/40/use the up/down arrows or scroll wheel.
这是 JSFiddle http://jsfiddle.net/9R4hZ/40/使用向上/向下箭头或滚轮。
Using padding and margin for the positioning are probably why you're experiencing rendering issues. While my code uses scroll or keyboard input for the effect you can loop the relavent portion and check the $moving variable until you reach the desired element on screen.
使用填充和边距进行定位可能是您遇到渲染问题的原因。虽然我的代码使用滚动或键盘输入来实现效果,但您可以循环相关部分并检查 $moving 变量,直到到达屏幕上所需的元素。
function parallaxScroll(scroll) {
// current moving object
var ml = $moving.position().left;
var mt = $moving.position().top;
var mw = $moving.width();
var mh = $moving.height();
// calc velocity
var fromTop = false;
var fromBottom = false;
var fromLeft = false;
var fromRight = false;
var vLeft = 0;
var vTop = 0;
if($moving.hasClass('from-top')) {
vTop = scroll;
fromTop = true;
} else if($moving.hasClass('from-bottom')) {
vTop = -scroll;
fromBottom = true;
} else if($moving.hasClass('from-left')) {
vLeft = scroll;
fromLeft = true;
} else if($moving.hasClass('from-right')) {
vLeft = -scroll;
fromRight = true;
}
// calc new position
var newLeft = ml + vLeft;
var newTop = mt + vTop;
// check bounds
var finished = false;
if(fromTop && (newTop > t || newTop + mh < t)) {
finished = true;
newTop = (scroll > 0 ? t : t - mh);
} else if(fromBottom && (newTop < t || newTop > h)) {
finished = true;
newTop = (scroll > 0 ? t : t + h);
} else if(fromLeft && (newLeft > l || newLeft + mw < l)) {
finished = true;
newLeft = (scroll > 0 ? l : l - mw);
} else if(fromRight && (newLeft < l || newLeft > w)) {
finished = true;
newLeft = (scroll > 0 ? l : l + w);
}
// set new position
$moving.css('left', newLeft);
$moving.css('top', newTop);
// if finished change moving object
if(finished) {
// get the next moving
if(scroll > 0) {
$moving = $moving.next('.parallax');
if($moving.length == 0)
$moving = $view.find('.parallax:last');
} else {
$moving = $moving.prev('.parallax');
if($moving.length == 0)
$moving = $view.find('.parallax:first');
}
}
// for debug
$('#direction').text(scroll + " " + l + "/" + t + " " + ml + "/" + mt + " " + finished + " " + $moving.text());
}
回答by Jahmic
May not be related to your specifics, but I had a jumpy parallax scrolling problem, I was able to solve it adding the following CSS for the fixed portions of the page:
可能与您的具体情况无关,但我有一个跳跃的视差滚动问题,我能够解决它,为页面的固定部分添加以下 CSS:
@supports (background-attachment: fixed)
{
.fixed-background
{
background-attachment: fixed;
}
}
Not sure of all the specifics, but found at Alternate Fixed & Scroll Backgrounds
不确定所有细节,但可以在Alternate Fixed & Scroll Backgrounds 找到

