javascript - 在按键上应用滚动动画与在鼠标单击时相同
问题描述
我有一个水平展开的页面,可以通过鼠标单击或按Space Bar、Page Up / Page Down、Left Arrow / Right Arrow和Home / End键滚动。
通过鼠标点击激活的滚动使用Animate Plus
.
使用按键滚动时如何获得完全相同的动画?
由于我的代码不会在 Stack Overflow 的代码段中运行,因此我将其发布到 Codepen。
这是我的完整代码:
下面是我的 JavaScript 代码:
import animate from "https://cdn.jsdelivr.net/npm/animateplus@2/animateplus.js"
// Scroll on key presses
// =====================
let scrollPosition = 0
const maxScrollPosition = document.body.scrollWidth - window.innerWidth
const container = document.scrollingElement
window.onload = () => {
document.body.onkeydown = event => {
switch (event.code) {
case "Space":
case "PageDown":
case "ArrowRight":
case "ArrowDown": {
event.preventDefault()
if (scrollPosition === maxScrollPosition) return // If at the end, return
scrollPosition += window.innerWidth
break
}
case "PageUp":
case "ArrowLeft":
case "ArrowUp": {
event.preventDefault()
if (scrollPosition === 0) return // If at the beginning, return
scrollPosition -= window.innerWidth
break
}
case "Home": {
scrollPosition = 0
break
}
case "End": {
scrollPosition = container.scrollWidth
break
}
}
container.scrollTo({
top: 0,
left: scrollPosition
})
}
}
// Scroll on mouse clicks
// ======================
const goToPreviousSectionButton = document.createElement("button")
const goToNextSectionButton = document.createElement("button")
document.body.appendChild(goToPreviousSectionButton)
document.body.appendChild(goToNextSectionButton)
const sections = Array.from(document.querySelectorAll("section")).sort(
(s1, s2) => {
return s1.getBoundingClientRect().left - s2.getBoundingClientRect().left
}
)
const getSectionInView = () => {
const halfWidth = window.innerWidth / 2
const index = sections.findIndex(
section =>
section.getBoundingClientRect().left <= halfWidth &&
section.getBoundingClientRect().right > halfWidth
)
return index
}
const getNextSection = dir => {
const sectionInViewIndex = getSectionInView()
const nextIndex = sectionInViewIndex + dir
const numSections = sections.length
const nextSectionIndex =
nextIndex < 0 || nextIndex >= numSections ? sectionInViewIndex : nextIndex
return sections[nextSectionIndex]
}
const animateScroll = dir => {
const from = container.scrollLeft
const { left } = getNextSection(dir).getBoundingClientRect()
return progress => (container.scrollLeft = from + progress * left)
}
goToPreviousSectionButton.addEventListener("click", () => {
animate({
easing: "out-quintic",
change: animateScroll(-1)
})
})
goToNextSectionButton.addEventListener("click", () => {
animate({
easing: "out-quintic",
change: animateScroll(1)
})
})
解决方案
您可以在“开关”中使用ArrowRight和ArrowLeft案例。下面的用法将解决问题。
import animate from "https://cdn.jsdelivr.net/npm/animateplus@2/animateplus.js"
// Scroll on key presses
// =====================
let scrollPosition = 0
const maxScrollPosition = document.body.scrollWidth - window.innerWidth
const container = document.scrollingElement
window.onload = () => {
document.body.onkeydown = event => {
switch (event.code) {
case "Space":
case "PageDown":
case "ArrowRight":
{
scrollPosition++;
if (scrollPosition === 3) return
event.preventDefault()
animate({
easing: "out-quintic",
change: animateScroll(1)
})
break
}
case "ArrowLeft":
{
scrollPosition--;
if (scrollPosition === 0) return
event.preventDefault()
animate({
easing: "out-quintic",
change: animateScroll(-1)
})
break
}
case "PageUp":
case "Home": {
if(scrollPosition === 1)
{
animate({
easing: "out-quintic",
change: animateScroll(-1)
})
}else
{
animate({
easing: "out-quintic",
change: animateScroll(-2)
})
}
scrollPosition = 0;
break
}
case "End": {
if(scrollPosition === 1)
{
animate({
easing: "out-quintic",
change: animateScroll(1)
})
}else
{
animate({
easing: "out-quintic",
change: animateScroll(2)
})
}
scrollPosition = 2;
break
}
}
}
}
// Scroll on mouse clicks
// ======================
const goToPreviousSectionButton = document.createElement("button")
const goToNextSectionButton = document.createElement("button")
document.body.appendChild(goToPreviousSectionButton)
document.body.appendChild(goToNextSectionButton)
const sections = Array.from(document.querySelectorAll("section")).sort(
(s1, s2) => {
return s1.getBoundingClientRect().left - s2.getBoundingClientRect().left
}
)
const getSectionInView = () => {
const halfWidth = window.innerWidth / 2
const index = sections.findIndex(
section =>
section.getBoundingClientRect().left <= halfWidth &&
section.getBoundingClientRect().right > halfWidth
)
return index
}
const getNextSection = dir => {
const sectionInViewIndex = getSectionInView()
const nextIndex = sectionInViewIndex + dir
const numSections = sections.length
const nextSectionIndex =
nextIndex < 0 || nextIndex >= numSections ? sectionInViewIndex : nextIndex
return sections[nextSectionIndex]
}
const animateScroll = dir => {
const from = container.scrollLeft
const { left } = getNextSection(dir).getBoundingClientRect()
return progress => (container.scrollLeft = from + progress * left)
}
goToPreviousSectionButton.addEventListener("click", () => {
animate({
easing: "out-quintic",
change: animateScroll(-1)
})
})
goToNextSectionButton.addEventListener("click", () => {
animate({
easing: "out-quintic",
change: animateScroll(1)
})
})
推荐阅读
- flutter - Flutter:无法让 SingleChildScrollView 中的容器垂直扩展
- php - HTML 表单到 CSV 并使用 PHP 下载 CSV
- javascript - 从对象内的函数数组中的回调函数访问正确的“this”
- xml - 如何一次获取 DOMDocument.Validate 中的所有验证错误?
- c# - 如何避免由于独特的约束而标记为未更改并稍后修改?
- azure - 如何使用逻辑应用修改 Azure 分析服务角色?
- java - Hibernate - 在查询中映射多个枚举集
- ms-access - 访问选择查询,其中源字段基于另一列
- excel - 使用 VB.net 读取/转换 PIPE 分隔的 txt 文件
- html - 网站没有显示响应