Javascript 视差元件毛刺

Javascript 视差元件毛刺,javascript,html,css,parallax,Javascript,Html,Css,Parallax,所以,我一直在试图用我的头来环绕这个被称为视差的整洁效果。基本上,背景滚动比前景元素慢 我发现了这个新的“把戏”,它正在发挥作用。随着滚动的进行,更改top属性以创建视差效果 问题… 因此,为了提高性能,并在元素不在用户视口中时消除CPU的压力,我创建了一个if语句,检查top位置是否超过300px。如果是,它将覆盖所有内容并将top属性设置回0,因此它不会无缘无故地不断增加它 现在,只需滚动一点。看到了吗,当红色的div盖过白色的时候,白色的口吃了吗?查看DOM检查器,我看到if语句异常,将t

所以,我一直在试图用我的头来环绕这个被称为视差的整洁效果。基本上,背景滚动比前景元素慢

我发现了这个新的“把戏”,它正在发挥作用。随着滚动的进行,更改
top
属性以创建视差效果

问题…

因此,为了提高性能,并在元素不在用户视口中时消除CPU的压力,我创建了一个
if
语句,检查
top
位置是否超过300px。如果是,它将覆盖所有内容并将
top
属性设置回0,因此它不会无缘无故地不断增加它

现在,只需滚动一点。看到了吗,当红色的
div
盖过白色的时候,白色的口吃了吗?查看DOM检查器,我看到
if
语句异常,将
top
属性设置为0px,即使它不超过300px。哈尔普

在我们讨论这个问题时,我很想看到更多关于视差效果的建议。我已经看到了一些关于这种效应的答案,但它们似乎。。。对我来说太复杂了。我知道有更好的方法,我知道有

而且,如果没有jQuery的答案,我们将不胜感激。谢谢

var txtfirst=document.getElementById(“txtfirst”);
window.onscroll=函数(){
var ypos=window.pageYOffset;
txtfirst.style.top=ypos*0.4+“px”;
如果(txtfirst.style.top>'300px'){
txtfirst.style.top='0px';
}
}
html,正文{
保证金:0;
填充:0;
宽度:100%;
身高:100%;
}
.文本优先{
显示器:flex;
文本对齐:居中;
证明内容:中心;
对齐项目:居中;
字体大小:32px;
字体系列:Arial;
颜色:灰色;
宽度:100%;
高度:500px;
位置:相对位置;
}
.前景红{
宽度:100%;
高度:600px;
背景色:红色;
显示器:flex;
证明内容:中心;
对齐项目:居中;
字体系列:Arial;
颜色:灰色;
字体大小:32px;
}
.spacer{/*用于滚动*/
宽度:100%;
高度:1000px;
}
这是一些文本
这应该在上面

您的应用程序很可能(我假设您只提供了选定的代码片段)不起作用,至少因为您在尝试优化时,在比较数字时正在比较文本:

txtfirst.style.top > '300px'
上面的行为与您预期的不同。
元素::style
属性的每个属性(例如,在您的示例中,
txtfirst.style
)都是a,而不是a。像
“50px”<“300px”
这样的测试不会比较50是否小于300,而是比较文本值

如果确实要比较像素量,可以使用
parseInt
函数将
50px
之类的值转换为数字50。然后,您的测试将如下所示:

parseInt(txtfirst.style.top) < 300
上面的
规则
函数从第一个找到的样式表(您只有一个)返回带有匹配选择器(例如
.text first
html,body
)的CSS规则(其中包含设置的CSS属性)。规则的
style
属性是指包含规则中设置的所有CSS属性的对象。其行为与内联样式对象相同。注意,您没有在上面任何地方使用内联样式,而是写入样式表对象(由文档的
..
片段初始化)并读回计算值

修复使用
滚动
事件进行动画时出现的问题 首先,您知道旧版本的iOS没有在您滚动时触发
scroll
事件吗?这将使视差效果完全停止,因为在用户停止滚动后将触发一个
滚动
事件。这与浏览器进行页面滚动的方式有关——为了使用有限的移动CPU资源实现平滑的页面滚动动画,每秒运行
滚动
事件处理程序提供的JavaScript代码被认为是一个过于慷慨的提议,苹果转而选择了有争议的解决方案,他们被良好的用户体验所占据

无论如何,如果不使用
滚动
事件,该怎么办?您可以使用良好的旧
setInterval

function rule(selector) {
    var sheet = document.styleSheets[0];
    return Array.prototype.find.call(sheet.cssRules, rule => rule.selectorText == selector);
}
var txtfirst = document.getElementById("txtfirst");
var old_window_pageYOffset = window.pageYOffset;
setTimeout(function() {    
    var ypos = window.pageYOffset;
    if(ypos != old_window_pageYOffset) return;
    old_window_pageYOffset = ypos;
    var style = rule(".text-first").style;
    style.top = ypos * 0.4 + "px";
    if(parseInt(getComputedStyle(txtfirst).top) > 300) {
        style.top = "0px";
    }
}, 1000 / 60);
上面所做的是确保在页面的整个生命周期内每秒调用函数60次,但在每次调用时检查窗口的滚动位置是否自上次调用以来发生了更改,仅在有更改时调用旧代码,否则不执行任何操作。这显然根本不使用
滚动
事件。综上所述,较新的iOS版本已经恢复了这种行为,
scroll
事件会随着滚动位置的每次更改而触发。这意味着您可能只想将其作为基线,并依赖于事件,而不是
setInterval
。后者的一个免费好处是,您可以控制视差效果的运行速率

我还可以建议使用
requestAnimationFrame
,这比
setInterval
更“智能”,因为如果用户代理认为不需要动画,例如如果整个页面选项卡此时不可见或与用户不交互,它将不会调用代码。请放心,您的动画将“在需要时”运行:

上面的代码是对视差效果的一个不错的尝试,除了一些与视差效果无关的小细节:

  • 当我们有
    addEventListener
    时,我不使用*name*
函数族上的
。前者是每个处理程序的一个属性,不能保证脚本是这些属性的唯一使用者——它们可能已经由浏览器扩展设置。我们可以争论,网页作者是否拥有独家所有权,是否可以访问他们可以获得的所有属性,但至少我有ex
function rule(selector) {
    var sheet = document.styleSheets[0];
    return Array.prototype.find.call(sheet.cssRules, rule => rule.selectorText == selector);
}
var txtfirst = document.getElementById("txtfirst");
var old_window_pageYOffset = window.pageYOffset;
setTimeout(function() {    
    var ypos = window.pageYOffset;
    if(ypos != old_window_pageYOffset) return;
    old_window_pageYOffset = ypos;
    var style = rule(".text-first").style;
    style.top = ypos * 0.4 + "px";
    if(parseInt(getComputedStyle(txtfirst).top) > 300) {
        style.top = "0px";
    }
}, 1000 / 60);
function rule(selector) {
    var sheet = document.styleSheets[0];
    return Array.prototype.find.call(sheet.cssRules, rule => rule.selectorText == selector);
}
var txtfirst = document.getElementById("txtfirst");
var old_window_pageYOffset = window.pageYOffset;
requestAnimationFrame(function() {    
    var ypos = window.pageYOffset;
    if(ypos != old_window_pageYOffset) return;
    old_window_pageYOffset = ypos;
    var style = rule(".text-first").style;
    style.top = ypos * 0.4 + "px";
    if(parseInt(getComputedStyle(txtfirst).top) > 300) {
        style.top = "0px";
    }
});