使用纯 JS 滚动到 div(不是 window)内的位置
Scroll to position WITHIN a div (not window) using pure JS
请仅使用纯 JS - 否 JQUERY
我有一个带溢出滚动的 div,window (html/body) 永远不会溢出。
我有一个锚链接列表,希望在单击它们时滚动到某个位置。
基本上只是在 div 中寻找锚点滚动,而不是 window。
window.scrollTo 等不起作用,因为 window 实际上从未溢出。
简单测试用例http://codepen.io/mildrenben/pen/RPyzqm
翡翠
nav
a(data-goto="#1") 1
a(data-goto="#2") 2
a(data-goto="#3") 3
a(data-goto="#4") 4
a(data-goto="#5") 5
a(data-goto="#6") 6
main
p(data-id="1") 1
p(data-id="2") 2
p(data-id="3") 3
p(data-id="4") 4
p(data-id="5") 5
p(data-id="6") 6
SCSS
html, body {
width: 100%;
height: 100%;
max-height: 100%;
}
main {
height: 100%;
max-height: 100%;
overflow: scroll;
width: 500px;
}
nav {
background: red;
color: white;
position: fixed;
width: 50%;
left: 50%;
}
a {
color: white;
cursor: pointer;
display: block;
padding: 10px 20px;
&:hover {
background: lighten(red, 20%);
}
}
p {
width: 400px;
height: 400px;
border: solid 2px green;
padding: 30px;
}
JS
var links = document.querySelectorAll('a'),
paras = document.querySelectorAll('p'),
main = document.querySelector('main');
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function(){
var linkID = this.getAttribute('data-goto').slice(1);
for (var j = 0; j < links.length; j++) {
if(linkID === paras[j].getAttribute('data-id')) {
window.scrollTo(0, paras[j].offsetTop);
}
}
})
}
请仅使用纯 JS - 否 JQUERY
我希望我现在能正确理解这个问题:您有无法更改的标记(因为它是通过某种您无法控制的方式生成的)并且想使用 JS 向生成的菜单项添加功能。
我的建议是分别向目标和菜单项添加 id
和 href
属性,如下所示:
var links = document.querySelectorAll('a'),
paras = document.querySelectorAll('p');
for (var i = 0; i < links.length; i++) {
links[i].href=links[i].getAttribute('data-goto');
}
for (var i = 0; i < paras.length; i++) {
paras[i].id=paras[i].getAttribute('data-id');
}
你想要的是设置 scrollTop
property on the <main>
element.
var nav = document.querySelector('nav'),
main = document.querySelector('main');
nav.addEventListener('click', function(event){
var linkID,
scrollTarget;
if (event.target.tagName.toUpperCase() === "A") {
linkID = event.target.dataset.goto.slice(1);
scrollTarget = main.querySelector('[data-id="' + linkID + '"]');
main.scrollTop = scrollTarget.offsetTop;
}
});
你会注意到我做的其他一些不同的事情:
- 我使用了 event delegation,所以我只需要将一个事件附加到
nav
元素,这将更有效地处理对任何链接的点击。
- 同样,我没有遍历所有
p
元素,而是使用 attribute selector 选择了我想要的元素
这不仅效率更高、可扩展性更高,而且生成的代码更短、更易于维护。
此代码将直接跳转到元素,对于动画滚动,您需要编写一个 incrementally updates scrollTop
after small delays using setTimeout
.
的函数
var nav = document.querySelector('nav'),
main = document.querySelector('main'),
scrollElementTo = (function () {
var timerId;
return function (scrollWithin, scrollTo, pixelsPerSecond) {
scrollWithin.scrollTop = scrollWithin.scrollTop || 0;
var pixelsPerTick = pixelsPerSecond / 100,
destY = scrollTo.offsetTop,
direction = scrollWithin.scrollTop < destY ? 1 : -1,
doTick = function () {
var distLeft = Math.abs(scrollWithin.scrollTop - destY),
moveBy = Math.min(pixelsPerTick, distLeft);
scrollWithin.scrollTop += moveBy * direction;
if (distLeft > 0) {
timerId = setTimeout(doTick, 10);
}
};
clearTimeout(timerId);
doTick();
};
}());
nav.addEventListener('click', function(event) {
var linkID,
scrollTarget;
if (event.target.tagName.toUpperCase() === "A") {
linkID = event.target.dataset.goto.slice(1);
scrollTarget = main.querySelector('[data-id="' + linkID + '"]');
scrollElementTo(main, scrollTarget, 500);
}
});
事件委托可能会遇到的另一个问题是,如果 a
元素包含子元素并且单击了子元素,它将成为事件的目标而不是 a
标签本身。您可以使用 getParentAnchor
function I wrote here.
之类的方法来解决这个问题
请仅使用纯 JS - 否 JQUERY
我有一个带溢出滚动的 div,window (html/body) 永远不会溢出。
我有一个锚链接列表,希望在单击它们时滚动到某个位置。
基本上只是在 div 中寻找锚点滚动,而不是 window。
window.scrollTo 等不起作用,因为 window 实际上从未溢出。
简单测试用例http://codepen.io/mildrenben/pen/RPyzqm
翡翠
nav
a(data-goto="#1") 1
a(data-goto="#2") 2
a(data-goto="#3") 3
a(data-goto="#4") 4
a(data-goto="#5") 5
a(data-goto="#6") 6
main
p(data-id="1") 1
p(data-id="2") 2
p(data-id="3") 3
p(data-id="4") 4
p(data-id="5") 5
p(data-id="6") 6
SCSS
html, body {
width: 100%;
height: 100%;
max-height: 100%;
}
main {
height: 100%;
max-height: 100%;
overflow: scroll;
width: 500px;
}
nav {
background: red;
color: white;
position: fixed;
width: 50%;
left: 50%;
}
a {
color: white;
cursor: pointer;
display: block;
padding: 10px 20px;
&:hover {
background: lighten(red, 20%);
}
}
p {
width: 400px;
height: 400px;
border: solid 2px green;
padding: 30px;
}
JS
var links = document.querySelectorAll('a'),
paras = document.querySelectorAll('p'),
main = document.querySelector('main');
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function(){
var linkID = this.getAttribute('data-goto').slice(1);
for (var j = 0; j < links.length; j++) {
if(linkID === paras[j].getAttribute('data-id')) {
window.scrollTo(0, paras[j].offsetTop);
}
}
})
}
请仅使用纯 JS - 否 JQUERY
我希望我现在能正确理解这个问题:您有无法更改的标记(因为它是通过某种您无法控制的方式生成的)并且想使用 JS 向生成的菜单项添加功能。
我的建议是分别向目标和菜单项添加 id
和 href
属性,如下所示:
var links = document.querySelectorAll('a'),
paras = document.querySelectorAll('p');
for (var i = 0; i < links.length; i++) {
links[i].href=links[i].getAttribute('data-goto');
}
for (var i = 0; i < paras.length; i++) {
paras[i].id=paras[i].getAttribute('data-id');
}
你想要的是设置 scrollTop
property on the <main>
element.
var nav = document.querySelector('nav'),
main = document.querySelector('main');
nav.addEventListener('click', function(event){
var linkID,
scrollTarget;
if (event.target.tagName.toUpperCase() === "A") {
linkID = event.target.dataset.goto.slice(1);
scrollTarget = main.querySelector('[data-id="' + linkID + '"]');
main.scrollTop = scrollTarget.offsetTop;
}
});
你会注意到我做的其他一些不同的事情:
- 我使用了 event delegation,所以我只需要将一个事件附加到
nav
元素,这将更有效地处理对任何链接的点击。 - 同样,我没有遍历所有
p
元素,而是使用 attribute selector 选择了我想要的元素
这不仅效率更高、可扩展性更高,而且生成的代码更短、更易于维护。
此代码将直接跳转到元素,对于动画滚动,您需要编写一个 incrementally updates scrollTop
after small delays using setTimeout
.
var nav = document.querySelector('nav'),
main = document.querySelector('main'),
scrollElementTo = (function () {
var timerId;
return function (scrollWithin, scrollTo, pixelsPerSecond) {
scrollWithin.scrollTop = scrollWithin.scrollTop || 0;
var pixelsPerTick = pixelsPerSecond / 100,
destY = scrollTo.offsetTop,
direction = scrollWithin.scrollTop < destY ? 1 : -1,
doTick = function () {
var distLeft = Math.abs(scrollWithin.scrollTop - destY),
moveBy = Math.min(pixelsPerTick, distLeft);
scrollWithin.scrollTop += moveBy * direction;
if (distLeft > 0) {
timerId = setTimeout(doTick, 10);
}
};
clearTimeout(timerId);
doTick();
};
}());
nav.addEventListener('click', function(event) {
var linkID,
scrollTarget;
if (event.target.tagName.toUpperCase() === "A") {
linkID = event.target.dataset.goto.slice(1);
scrollTarget = main.querySelector('[data-id="' + linkID + '"]');
scrollElementTo(main, scrollTarget, 500);
}
});
事件委托可能会遇到的另一个问题是,如果 a
元素包含子元素并且单击了子元素,它将成为事件的目标而不是 a
标签本身。您可以使用 getParentAnchor
function I wrote here.