javascript - 平滑滚动,跨浏览器,无需 jQuery
问题描述
您将在下面找到我为在单击本地链接时平滑滚动而创建的脚本。它是通过transform
(没有jQuery)完成的。正如所见,我已经使用内联 CSS和外部样式表实现了它。我推荐内联版本,因为可能很难猜测相关样式表的索引。
然而,问题在于滚动条的实际移动是在应用转换之后发生的。因此,如果您在滚动转换完成之前单击链接,则代码行为异常。
关于解决这个问题的任何想法?
编辑:
我知道那里有jQuery 解决方案和第三方 polyfill 库。然而,我的目标是用普通的 JavaScript重新创建jQuery功能。
我的脚本:
// Get style rule's declaration block
function getStyleDeclaration(styleSheet, selectorText) {
const rules = styleSheet.cssRules;
return Array.from(rules).find(r => r.selectorText === selectorText).style;
// for (let i = 0; i < rules.length; i += 1) {
// if (rules[i].selectorText === selectorText) return rules[i].style;
// }
}
// Get specific style sheet, based on its title
// Many style sheets do not have a title however
// Which is main reason it is preferred to work with
// inline styles instead
function getStyleSheet(title) {
const styleSheets = document.styleSheets;
return Array.from(styleSheets).find(s => s.title === title);
// for (let i = 0; i < styleSheets.length; i += 1) {
// if (styleSheets[i].title === title) return styleSheets[i];
// }
}
function scrollToElement_ExternalStyleSheet(anchor, target) {
anchor.addEventListener("click", e => {
e.preventDefault();
const time = 1000;
// Distance from viewport to topof target
const distance = -target.getBoundingClientRect().top;
// Modify external style sheet
const transStyle = getStyleDeclaration(document.styleSheets[1], ".trans");
transStyle.transform = "translate(0, " + distance + "px)";
transStyle.transition = "transform " + time + "ms ease";
const root = document.documentElement; // <html> element
root.classList.add("trans");
window.setTimeout(() => {
root.classList.remove("trans");
root.scrollTo(0, -distance + window.pageYOffset);
}, time);
});
}
function scrollToElement_InlineStyle(anchor, target) {
const root = document.documentElement;
anchor.addEventListener('click', e => {
e.preventDefault();
const time = 900;
const distance = -target.getBoundingClientRect().top;
root.style.transform = 'translate(0, ' + distance + 'px)';
root.style.transition = 'transform ' + time + 'ms ease';
window.setTimeout(() => {
root.scrollTo(0, -distance + window.pageYOffset);
root.style.transform = null; // Revert to default
root.style.transition = null;
}, time);
});
}
function applySmoothScroll() {
const anchors = document.querySelectorAll("a");
const localAnchors = Array.from(anchors).filter(
a => a.getAttribute("href").indexOf("#") != -1
);
localAnchors.forEach(a => {
const targetString = a.getAttribute("href");
const target = document.querySelector(targetString);
// scrollToElement_ExternalStyleSheet(a, target);
scrollToElement_InlineStyle(a, target);
});
}
applySmoothScroll();
.box {
padding-bottom: 300px;
padding-top: 0.5rem;
background-color: orange;
text-align: center;
font-size: 200%;
}
.box:nth-child(even) {
background-color: lightblue;
color: white;
}
a {
color: black;
}
body {
margin: 0;
}
.trans {
transform: translate(0, -100px);
transition: transform 900ms ease;
}
<div id="s0" class="box"><a href="#s1">Click Me!</a></div>
<div id="s1" class="box"><a href="#s2">Click Me!</a></div>
<div id="s2" class="box"><a href="#s0">Click Me!</a></div>
解决方案
推荐阅读
- ios - 无法从 Apple HealthKit 访问 Active Energy 的汇总日值
- discord.py - “except”函数不适用于 discord.py
- c++ - boost::extension.hpp 的原因没有为无序容器和其他一些容器定义 hash_value()
- python - FileNotFoundError: [Errno 2] No such file or directory Azure Python 错误
- amazon-web-services - 安装 Hudi 版本。AWS EMR 上的 0.6.0
- python - 使用 HoughCircles 和 FindContours 查找不同曝光的圆圈
- istio - 如何将 kube-secret 映射为 istio 键的值:“何时”条件下的 request.headers?
- c# - 无法在自定义 C# 异常中访问 StackTrace
- javascript - 此标头有什么问题:标头链接引用到不同的 url?
- elixir - 如何编辑回显服务器以允许多个客户端交换消息