Javascript JQuery-加载并直接转到带有锚的URL时获取偏移量
我尝试添加以下功能:当我键入带有锚的URL时,我希望直接位于锚上。我的问题是,我有一个固定的页眉,而我当前的JQuery代码没有考虑我放置的偏移量(Javascript JQuery-加载并直接转到带有锚的URL时获取偏移量,javascript,jquery,Javascript,Jquery,我尝试添加以下功能:当我键入带有锚的URL时,我希望直接位于锚上。我的问题是,我有一个固定的页眉,而我当前的JQuery代码没有考虑我放置的偏移量(55,即页眉高度) 下面是代码片段: if ($(location.href.split("#")[1])) { var target = $('#'+location.href.split("#")[1]); if (target.length) { var hash = this.hash; $('
55
,即页眉高度
)
下面是代码片段:
if ($(location.href.split("#")[1])) {
var target = $('#'+location.href.split("#")[1]);
if (target.length) {
var hash = this.hash;
$('html,body').animate({ scrollTop: target.offset().top - 55 }, 300, function() {
location.hash = hash;
});
}
}
此代码段位于[anchor.js][1]脚本中
我很好地重定向到锚,但是,无论我采用什么偏移量值,最终结果都不会考虑这一点,因此在加载页面后,锚名称被固定标题隐藏
如果有人能帮我解决这个问题
提前谢谢
ps:我只想让它在Firefox和Chrome上运行
更新
看来解决办法可以从哪里来
为此,我必须在
标记之前插入一个
标记,带有class='direct\u anchor'
(带有.before
Jquery函数),因此我在CSS中包含以下规则:
.direct_anchor {
display: block;
height: 55px; // Height of fixed header
margin-top: -55px;
visibility: hidden;
}
最后,这里是我直接在地址栏中键入带有哈希扩展名的URL的代码片段:
var target = $('[name="'+location.href.split("#")[1]+'"]');
var hash = location.href.split("#")[1];
if (target.length) {
location.hash = hash;
$('html,body').animate({ scrollTop: target.offset().top - 55 }, 300);
target.before( "<span class='direct_anchor'></span>" );
}
var target=$('[name=“”+location.href.split(“#”)[1]+'];
var hash=location.href.split(“#”)[1];
if(目标长度){
location.hash=hash;
$('html,body').animate({scrollTop:target.offset().top-55},300);
目标。在(“”)之前;
}
不幸的是,我无法让它工作,class='direct\u-anchor'
CSS规则似乎没有应用到span
标记上
我不是Jquery的专家,任何人都能看出哪里出了问题
感谢您的帮助。尝试在播放动画之前更改位置哈希
location.hash = this.hash;
$('html, body').animate({scrollTop: target.offset().top -55 }, 300);
在动画之后更改它会导致页面跳回目标,而不带偏移量。我调试后发现脚本在重新加载时不会在if语句中执行
$(window).bind("load", function () {
$('a[href*="#"]:not([href="#SECTION"]):not([href*="wikipedia"]):not([href*="mjx-eqn"])').click(function(event) {
event.preventDefault();
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
if (target.length) {
var hash = this.hash;
$('html,body').animate({ scrollTop: target.offset().top - 55 }, 300, function() {
href = window.location.href;
history.pushState({page:href}, null, href.split('#')[0]+hash);
});
return false;
}
}
});
$(window).bind('popstate', function(event) {
var state = event.originalEvent.state;
var target = window.location.href.split('#');
var href = target[0];
if (state) {
$('html,body').animate({ scrollTop: 0 }, 300, function() {
history.replaceState({}, null, href);
});
}
});
// code changed here
var target = $("[name='"+location.href.split("#")[1]+"']");
if (target.length) {
$('html,body').animate({ scrollTop: target.offset().top-55},300);
}
});
请注意,您可以使用
name
而不是id
作为选择器来获取元素。这是一个现在已经解决的问题。我已经通过调试进行了检查,所以不能确定,但它在chrome中运行良好。我无法签入firefox,因为我不知道如何使用调试器编辑脚本。有趣的是,几天前我在博客上遇到了完全相同的问题。问题不在于代码,而在于浏览器实现,它会等待一点和/或多次尝试将哈希值与页面上的id匹配。在我的例子中,ID是用Javascript生成的,浏览器仍然可以访问它们。您的代码可能会被执行,然后浏览器仍会转到该点
我的解决方案是在散列中插入一个实际携带id的不可见元素,并使其位置相对,位于前50px。作为一个通用的解决方案,我认为您唯一的(丑陋的)选择是检查id与哈希相同的元素的偏移量,并且仅在检测到浏览器移动它或超时后滚动容器
下面是解决方案的演示(在JSFIDLE中不起作用)。请注意,这里我立即执行脚本,因此如果页面加载时间较长,您可能需要增加超时时间。另一个解决方案是在DOMready上运行它,但我认为这会给您带来尴尬的延迟
<html>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js'></script>
<style>
header {
height:50px;
width:100%;
background:wheat;
position:fixed;
top:0;
}
#target {
color:red;
}
#topHalf, #bottomHalf {
margin-left:20%;
width:50%;
height:2000px;
background-color:gray;
}
</style>
<script>
(function() {
if (!location.hash) return;
var timeout=1000; //1 second. You may want to wait more
var done=false;
var interval=setInterval(function() {
var elem=document.getElementById(location.hash.substr(1));//hash can be '#id,div.aClass' or similar
if (!elem) return;
elem=$(elem);
var ofs=elem.offset();
if (!ofs||!ofs.top) return;
timeout-=100; //interval time
var scrollY=$(window).scrollTop(); //window to get scrollTop, not html,body which yields 0 on Chrome
if (Math.abs(ofs.top-scrollY)<55) { //header size, just to be sure
done=true; // if we are close, then probably the browser did its thing
clearInterval(interval);
$('html,body').animate({ scrollTop: ofs.top - 55 }, 300);
}
if (timeout<=0) { //otherwise, just do it on timeout
clearInterval(interval);
if (!done) $('html,body').animate({ scrollTop: ofs.top - 55 }, 300);
}
},100);
})();
</script>
<header></header>
<content>
<div id="topHalf"></div>
<a id="target">This is the target</a>
<div id="bottomHalf"></div>
</content>
<script>
var k=0;
for (var i=0; i<100000000; i++) {
//some slow running code
k+=Math.random();
}
document.write('K:',k); // using k so that it doesn't get optimized away
</script>
End
</html>
标题{
高度:50px;
宽度:100%;
背景:小麦;
位置:固定;
排名:0;
}
#目标{
颜色:红色;
}
#上半部,#下半部{
左缘:20%;
宽度:50%;
高度:2000px;
背景颜色:灰色;
}
(功能(){
如果(!location.hash)返回;
var timeout=1000;//1秒。您可能需要等待更长时间
var done=false;
var interval=setInterval(函数(){
var elem=document.getElementById(location.hash.substr(1));//哈希可以是“#id,div.aClass”或类似的值
如果(!elem)返回;
elem=$(elem);
变量ofs=元素偏移量();
如果(!ofs | |!ofs.top)返回;
超时-=100;//间隔时间
var scrollY=$(window).scrollTop();//获取scrollTop而不是html的窗口,在Chrome上生成0
如果(Math.abs(ofs.top scrollY)只需在h4上方为锚创建一个div。例如:
<div id="simulation"></div>
我不确定JavaScript是否是最好的方法。如果你的标题是固定的,你可以在CSS的主内容包装器中添加55px的padding top,这应该可以做到。如果($(location.href.split(“#”)[1])
应该实现什么?这是我来自外部URL(而不是我的网站)的情况我试图通过在浏览器中键入URL“”直接转到定位点,$(location.href.split(“#”)的值是多少
?我的意思是你想在这里检查什么。我检查在#符号之后是否有字符串,也就是检查URL中是否有锚。我想说的是,你实际上不需要为此使用jquery$
。你可以直接检查location.hash
的长度。我不确定你的意思是标题显示为f谢谢,你的解决方案在chrome上无法系统地工作(可能是缓存或历史记录有问题),我一直在尝试在firefox上调试它。regardsCan可以在$(window.load)中添加最后更改的代码(function(){//to add here});我在控制台编辑您的脚本时没有遇到任何问题,我以这种方式绑定load event listener。但现在,当您更新脚本时,我会随机遇到问题。请检查/js/anchor.js中的第56行,其中以冒号(:)而不是分号(;)结尾。引发错误。
#simulation {
position: relative;
bottom: 50px;
}