行为的滚动持续时间 = 在不同浏览器中平滑
Scroll duration for behaviour = smooth in different browsers
我想使用具有流畅行为的 window.scrollTo 函数。
例如:
window.scrollTo({ top: 0, behavior: 'smooth' })
平行我想改变一个元素的颜色。为此,我可以使用滚动事件来计算当前滚动位置的颜色。但这会导致性能不佳,因为滚动回调将经常调用。
更好的解决方案是同时开始过渡。但是为此我必须知道滚动持续时间。由于无法手动定义它,我需要知道浏览器使用的持续时间。
我在评论中分享的代码示例仅供参考。您还需要根据自己的滚动页面需求修改代码。
在这里,我尝试修改那个示例代码来滚动页面。
$(window).scroll(function() {
// selectors
var $window = $(window),
$body = $('body'),
$panel = $('.panel');
// Change 33% earlier than scroll position so colour is there when you arrive.
var scroll = $window.scrollTop() + ($window.height() / 3);
$panel.each(function () {
var $this = $(this);
// if position is within range of this panel.
// So position of (position of top of div <= scroll position) && (position of bottom of div > scroll position).
// Remember we set the scroll to 33% earlier in scroll var.
if ($this.position().top <= scroll && $this.position().top + $this.height() > scroll) {
// Remove all classes on body with color-
$body.removeClass(function (index, css) {
return (css.match (/(^|\s)color-\S+/g) || []).join(' ');
});
// Add class of currently active div
$body.addClass('color-' + $(this).data('color'));
}
});
}).scroll();
$(document).ready(function(){
$("button").click(function(){
$("html, body").animate({
scrollTop: $("#bottom").offset().top - 220
}, 8000);
// document.getElementById('bottom').scrollIntoView({behavior: "smooth"});
});
});
/* Setting fade transition and default settings */
body {
color: #000;
background-color: #f4f4f4;
transition: background-color 1s ease;
}
/* panel styles */
.panel {
/* min height incase content is higher than window height */
min-height: 100vh;
display: flex;
justify-content: space-around;
align-items: center;
font-family: sans-serif;
/* outline: 10px solid hotpink; */
/* turn above on to see the edge of panels */
}
/* colours */
.color-violet {
background-color: #7A4EAB;
}
.color-indigo {
background-color: #4332CF;
}
.color-blue {
background-color: #2F8FED;
}
.color-green {
background-color: #4DCF42;
}
.color-yellow {
background-color: #FAEB33;
}
.color-orange {
background-color: #F19031;
}
.color-red {
background-color: #F2293A;
}
/* styling for demo, can ignore */
body {
text-align: center;
font-size: 120%;
line-height: 1.618;
}
h1, h2 {
font-size: 3em;
letter-spacing: -0.05em;
line-height: 1.1;
}
p {
max-width: 30em;
margin-bottom: 1.618em;
}
a {
color: #4332CF;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div class="panel" data-color="white">
<div>
<h1>scrolling example</h1>
<div><button>Click me to scroll to bottom</button></div>
</div>
</div>
<div class="panel" data-color="violet">
<h2>Violet panel</h2>
</div>
<div class="panel" data-color="indigo">
<h2>Indigo panel</h2>
</div>
<div class="panel" data-color="blue">
<h2>Blue panel</h2>
</div>
<div class="panel" data-color="green">
<h2>Green panel</h2>
</div>
<div class="panel" data-color="yellow">
<h2>Yellow panel</h2>
</div>
<div class="panel" data-color="orange">
<h2>Orange panel</h2>
</div>
<div class="panel" data-color="red">
<h2>Red panel</h2>
</div>
<div id="bottom"></div>
MS Edge Chromium 浏览器中的输出:
此外,您可以尝试根据您的要求修改代码示例。
参考:
The scrolling box is scrolled in a smooth fashion
using a user-agent-defined timing function over a user-agent-defined period of time.
User agents should follow platform conventions, if any.
马上就使它成为一个复杂的问题,可能没有答案,或者至少没有可靠的答案。
浏览器可能
- 瞄准目标速度而不是持续时间,因此如果有多个页面要滚动,则滚动更长的时间
- 如果许多嵌套的滚动面板同时滚动,请调整滚动行为,例如一个接一个地排列它们(我看到 some code in Chromium 可能会做这样的事情)
- 允许user-configurable,这样视力不佳或晕车的人可以根据自己的喜好调整它,或禁用它
- 遵从操作系统,它可能有自己的怪癖和定制
- 更改其中任何一项,恕不另行通知,否则潜在的 OS 可能
这是 some Firefox code 中有关平滑滚动的评论的摘录。我没有深入研究这是否真的与你正在做的那种卷轴严格相关,但它给出了一个想法:
* |Smooth| scrolls have a symmetrical acceleration and deceleration curve
* modeled with a set of splines that guarantee that the destination will be
* reached over a fixed time interval. |Smooth| will only be smooth if smooth
* scrolling is actually enabled. This behavior is utilized by keyboard and
* mouse wheel scrolling events.
*
* |SmoothMsd| implements a physically based model that approximates the
* behavior of a mass-spring-damper system. |SmoothMsd| scrolls have a
* non-symmetrical acceleration and deceleration curve, can potentially
* overshoot the destination on intermediate frames, and complete over a
* variable time interval. |SmoothMsd| will only be smooth if cssom-view
* smooth-scrolling is enabled.
这里有一些代码供您自己测试。在我的实验中,我发现在 Firefox 和 Chromium 中,持续时间会根据滚动的距离而变化,而且我在每一个中都看到了不同的速度。
const qs = document.querySelector.bind(document);
const viewportHeightInput = qs("#viewport-height");
const contentHeightInput = qs("#content-height");
const viewport = qs("#viewport");
const content = qs("#content");
const output = qs("#output");
function update() {
viewport.style.height = `${viewportHeightInput.value}px`;
content.style.height = `${contentHeightInput.value}px`;
}
update();
viewportHeightInput.addEventListener("input", update);
contentHeightInput.addEventListener("input", update);
qs("#to-top").addEventListener("click", () => {
start = performance.now();
scrollEvents = 0;
updateScrollEvents();
viewport.scrollTo({
behavior: "smooth",
top: 0,
})
});
qs("#to-bottom").addEventListener("click", () => {
start = performance.now();
scrollEvents = 0;
updateScrollEvents();
viewport.scrollTo({
behavior: "smooth",
top: viewport.scrollHeight - viewport.clientHeight,
})
});
const scrollEventsOutput = qs("#scroll-events");
const elapsedOutput = qs("#elapsed");
let scrollEvents = 0;
let start = performance.now();
let last = null;
viewport.addEventListener("scroll", () => {
last = performance.now();
scrollEvents++;
updateScrollEvents();
});
function updateScrollEvents() {
scrollEventsOutput.value = scrollEvents;
elapsedOutput.value = last == null ? 0 : last - start;
}
#controls {
display: grid;
grid-template-columns: 10rem 1fr;
}
#controls fieldset {
display: contents;
}
#viewport {
overflow: auto;
border: thick solid orange;
margin: 4rem 0;
}
#content {
background-image: linear-gradient(to bottom left, black, white);
position: relative;
}
#content::before,
#content::after {
position: absolute;
left: 0;
background-color: black;
color: white;
display: block;
}
#content::before {
content: "start";
top: 0;
}
#content::after {
content: "end";
bottom: 0;
}
<div id="controls">
<fieldset>
<label for="viewport-height">Viewport height</label>
<input id="viewport-height" type="number" min="1" value="400">
</fieldset>
<fieldset>
<label for="content-height">Content height</label>
<input id="content-height" type="number" min="1" value="1000">
</fieldset>
<fieldset>
<label>Triggers</label>
<ul>
<li><button id="to-top">Scroll to top</button></li>
<li><button id="to-bottom">Scroll to bottom</button></li>
</ul>
</fieldset>
<fieldset>
<label for="scroll-events">Scroll events</label>
<input id="scroll-events" type="number" readonly value="0">
</fieldset>
<fieldset>
<label for="elapsed">Milliseconds between start of scroll and last scroll event</label>
<input id="elapsed" type="number" readonly value="0">
</fieldset>
</div>
<div id="viewport">
<div id="content"></div>
</div>
我想使用具有流畅行为的 window.scrollTo 函数。 例如:
window.scrollTo({ top: 0, behavior: 'smooth' })
平行我想改变一个元素的颜色。为此,我可以使用滚动事件来计算当前滚动位置的颜色。但这会导致性能不佳,因为滚动回调将经常调用。 更好的解决方案是同时开始过渡。但是为此我必须知道滚动持续时间。由于无法手动定义它,我需要知道浏览器使用的持续时间。
我在评论中分享的代码示例仅供参考。您还需要根据自己的滚动页面需求修改代码。
在这里,我尝试修改那个示例代码来滚动页面。
$(window).scroll(function() {
// selectors
var $window = $(window),
$body = $('body'),
$panel = $('.panel');
// Change 33% earlier than scroll position so colour is there when you arrive.
var scroll = $window.scrollTop() + ($window.height() / 3);
$panel.each(function () {
var $this = $(this);
// if position is within range of this panel.
// So position of (position of top of div <= scroll position) && (position of bottom of div > scroll position).
// Remember we set the scroll to 33% earlier in scroll var.
if ($this.position().top <= scroll && $this.position().top + $this.height() > scroll) {
// Remove all classes on body with color-
$body.removeClass(function (index, css) {
return (css.match (/(^|\s)color-\S+/g) || []).join(' ');
});
// Add class of currently active div
$body.addClass('color-' + $(this).data('color'));
}
});
}).scroll();
$(document).ready(function(){
$("button").click(function(){
$("html, body").animate({
scrollTop: $("#bottom").offset().top - 220
}, 8000);
// document.getElementById('bottom').scrollIntoView({behavior: "smooth"});
});
});
/* Setting fade transition and default settings */
body {
color: #000;
background-color: #f4f4f4;
transition: background-color 1s ease;
}
/* panel styles */
.panel {
/* min height incase content is higher than window height */
min-height: 100vh;
display: flex;
justify-content: space-around;
align-items: center;
font-family: sans-serif;
/* outline: 10px solid hotpink; */
/* turn above on to see the edge of panels */
}
/* colours */
.color-violet {
background-color: #7A4EAB;
}
.color-indigo {
background-color: #4332CF;
}
.color-blue {
background-color: #2F8FED;
}
.color-green {
background-color: #4DCF42;
}
.color-yellow {
background-color: #FAEB33;
}
.color-orange {
background-color: #F19031;
}
.color-red {
background-color: #F2293A;
}
/* styling for demo, can ignore */
body {
text-align: center;
font-size: 120%;
line-height: 1.618;
}
h1, h2 {
font-size: 3em;
letter-spacing: -0.05em;
line-height: 1.1;
}
p {
max-width: 30em;
margin-bottom: 1.618em;
}
a {
color: #4332CF;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div class="panel" data-color="white">
<div>
<h1>scrolling example</h1>
<div><button>Click me to scroll to bottom</button></div>
</div>
</div>
<div class="panel" data-color="violet">
<h2>Violet panel</h2>
</div>
<div class="panel" data-color="indigo">
<h2>Indigo panel</h2>
</div>
<div class="panel" data-color="blue">
<h2>Blue panel</h2>
</div>
<div class="panel" data-color="green">
<h2>Green panel</h2>
</div>
<div class="panel" data-color="yellow">
<h2>Yellow panel</h2>
</div>
<div class="panel" data-color="orange">
<h2>Orange panel</h2>
</div>
<div class="panel" data-color="red">
<h2>Red panel</h2>
</div>
<div id="bottom"></div>
MS Edge Chromium 浏览器中的输出:
此外,您可以尝试根据您的要求修改代码示例。
参考:
The scrolling box is scrolled in a smooth fashion using a user-agent-defined timing function over a user-agent-defined period of time. User agents should follow platform conventions, if any.
马上就使它成为一个复杂的问题,可能没有答案,或者至少没有可靠的答案。
浏览器可能
- 瞄准目标速度而不是持续时间,因此如果有多个页面要滚动,则滚动更长的时间
- 如果许多嵌套的滚动面板同时滚动,请调整滚动行为,例如一个接一个地排列它们(我看到 some code in Chromium 可能会做这样的事情)
- 允许user-configurable,这样视力不佳或晕车的人可以根据自己的喜好调整它,或禁用它
- 遵从操作系统,它可能有自己的怪癖和定制
- 更改其中任何一项,恕不另行通知,否则潜在的 OS 可能
这是 some Firefox code 中有关平滑滚动的评论的摘录。我没有深入研究这是否真的与你正在做的那种卷轴严格相关,但它给出了一个想法:
* |Smooth| scrolls have a symmetrical acceleration and deceleration curve * modeled with a set of splines that guarantee that the destination will be * reached over a fixed time interval. |Smooth| will only be smooth if smooth * scrolling is actually enabled. This behavior is utilized by keyboard and * mouse wheel scrolling events. * * |SmoothMsd| implements a physically based model that approximates the * behavior of a mass-spring-damper system. |SmoothMsd| scrolls have a * non-symmetrical acceleration and deceleration curve, can potentially * overshoot the destination on intermediate frames, and complete over a * variable time interval. |SmoothMsd| will only be smooth if cssom-view * smooth-scrolling is enabled.
这里有一些代码供您自己测试。在我的实验中,我发现在 Firefox 和 Chromium 中,持续时间会根据滚动的距离而变化,而且我在每一个中都看到了不同的速度。
const qs = document.querySelector.bind(document);
const viewportHeightInput = qs("#viewport-height");
const contentHeightInput = qs("#content-height");
const viewport = qs("#viewport");
const content = qs("#content");
const output = qs("#output");
function update() {
viewport.style.height = `${viewportHeightInput.value}px`;
content.style.height = `${contentHeightInput.value}px`;
}
update();
viewportHeightInput.addEventListener("input", update);
contentHeightInput.addEventListener("input", update);
qs("#to-top").addEventListener("click", () => {
start = performance.now();
scrollEvents = 0;
updateScrollEvents();
viewport.scrollTo({
behavior: "smooth",
top: 0,
})
});
qs("#to-bottom").addEventListener("click", () => {
start = performance.now();
scrollEvents = 0;
updateScrollEvents();
viewport.scrollTo({
behavior: "smooth",
top: viewport.scrollHeight - viewport.clientHeight,
})
});
const scrollEventsOutput = qs("#scroll-events");
const elapsedOutput = qs("#elapsed");
let scrollEvents = 0;
let start = performance.now();
let last = null;
viewport.addEventListener("scroll", () => {
last = performance.now();
scrollEvents++;
updateScrollEvents();
});
function updateScrollEvents() {
scrollEventsOutput.value = scrollEvents;
elapsedOutput.value = last == null ? 0 : last - start;
}
#controls {
display: grid;
grid-template-columns: 10rem 1fr;
}
#controls fieldset {
display: contents;
}
#viewport {
overflow: auto;
border: thick solid orange;
margin: 4rem 0;
}
#content {
background-image: linear-gradient(to bottom left, black, white);
position: relative;
}
#content::before,
#content::after {
position: absolute;
left: 0;
background-color: black;
color: white;
display: block;
}
#content::before {
content: "start";
top: 0;
}
#content::after {
content: "end";
bottom: 0;
}
<div id="controls">
<fieldset>
<label for="viewport-height">Viewport height</label>
<input id="viewport-height" type="number" min="1" value="400">
</fieldset>
<fieldset>
<label for="content-height">Content height</label>
<input id="content-height" type="number" min="1" value="1000">
</fieldset>
<fieldset>
<label>Triggers</label>
<ul>
<li><button id="to-top">Scroll to top</button></li>
<li><button id="to-bottom">Scroll to bottom</button></li>
</ul>
</fieldset>
<fieldset>
<label for="scroll-events">Scroll events</label>
<input id="scroll-events" type="number" readonly value="0">
</fieldset>
<fieldset>
<label for="elapsed">Milliseconds between start of scroll and last scroll event</label>
<input id="elapsed" type="number" readonly value="0">
</fieldset>
</div>
<div id="viewport">
<div id="content"></div>
</div>