今天来实现一个可翻页的笔记本~
在线体验
码上掘金
codePen
代码实现
页面配置信息
const pages = [
{
front: {
title: "《千与千寻》",
text: "少女千寻误入神灵世界,为救变成猪的父母经历磨难,最终以勇气与善意赢得自由。影片隐喻现代社会异化与人性救赎,获奥斯卡最佳动画长片+柏林金熊奖,全球票房超3.5亿美元,成为日本影史巅峰。",
background: "../images/宫崎骏/千与千寻.jpg",
},
back: {
title: "《天空之城》",
text: "吉卜力工作室开山之作。少年帕祖与持有飞行石的少女希达为阻止军方夺取古代浮空文明“拉普达”的毁灭性武器,展开空中冒险。影片探讨科技异化与人性贪婪,久石让的配乐成为经典,结尾的“生命之树”象征自然永恒。",
background: "../images/宫崎骏/天空之城.jpg",
},
},
…………
]
一个页面包含正面和背面,title 是页面的标题,text 是页面的文字内容,background是页面的背景图片。
页面创建
每一页都有正反两面,而且内容都不一样,根据配置信息将页面创建出来,封面和内部页面的样式有所不同,所以我们需要区分开来。
function createPage(info = {}, isCover = false) {
const pageElement = document.createElement("div");
const pre = isCover ? "cover" : "page";
if (info.background) {
const img = document.createElement("img");
img.classList.add(`${pre}-image`);
img.src = info.background;
pageElement.appendChild(img);
}
if (info.title) {
const titleElement = document.createElement("div");
titleElement.innerText = info.title;
titleElement.classList.add(`${pre}-title`);
pageElement.appendChild(titleElement);
}
const textElement = document.createElement("div");
textElement.innerText = info.text || "";
textElement.classList.add(`${pre}-text`);
pageElement.appendChild(textElement);
return pageElement;
}
function createFrontAndBackPage(pageElement, page = {}, isCover = false) {
if (!isCover) pageElement.classList.add("page");
pageElement.classList.add("turn-page");
const frontPage = createPage(page.front, isCover);
frontPage.classList.add("front-page");
const backPage = createPage(page.back, isCover);
backPage.classList.add("back-page");
pageElement.appendChild(frontPage);
pageElement.appendChild(backPage);
}
function createPages(page) {
pages.reverse().forEach((page, index) => {
const pageElement = document.createElement("span");
createFrontAndBackPage(pageElement, page);
pageElement.setAttribute("data-index", pages.length - index);
book.appendChild(pageElement);
});
}
翻页逻辑
翻页限制
- 向后翻页还没完成时不能往前翻页
if (target.classList.contains("turn")) {
if (isTurnIng === "turnBack") return;
}
- 向前翻页还没完成时不能往后翻页
else {
if (isTurnIng === "turn") return;
}
- 非当前显示在最前面的页面不允许翻页
if (![showPageNumber, showPageNumber - 1].includes(index)) {
return;
}
点击翻页
- 给所有页面都添加上点击事件
function turnPageFn() {
const coverElements = book.querySelectorAll(".cover");
const pageElements = book.querySelectorAll(".page");
pageElements.forEach((page, index) => {
page.addEventListener("click", pageClick);
});
coverElements.forEach((cover, index) => {
cover.addEventListener("click", pageClick);
});
}
- 判断翻页方向
function pageClick(e) {
const target = e.target;
const index = parseInt(target.getAttribute("data-index"));
if (![showPageNumber, showPageNumber - 1].includes(index)) {
return;
}
if (target.classList.contains("turn")) {
if (isTurnIng === "turnBack") return;
showPageNumber = index;
isTurnIng = "turn";
target.style.transform = "rotateY(-180deg)";
target.classList.remove("turn");
target.classList.add("turnBack");
target.style.zIndex = null;
} else {
if (isTurnIng === "turn") return;
showPageNumber = index + 1;
isTurnIng = "turnBack";
target.style.transform = "rotateY(0deg)";
target.classList.remove("turnBack");
target.classList.add("turn");
target.style.zIndex = calZIndex();
}
clearTimeout(timer);
timer = setTimeout(() => {
isTurnIng = false;
}, parseFloat(duration) * 1000);
}
css动画
正反页面切换
在翻页过程中需要将正反页面做一个切换,向前翻页到 90° 的时候切换显示正面,往后翻页到 90° 的时候切换显示背面。
.turn-page.turn > div.front-page {
animation: fadeOut var(--animation-duration) forwards;
}
.turn-page.turnBack > div.front-page {
animation: fadeIn var(--animation-duration) forwards;
}
.turn-page.turnBack > div.back-page {
animation: fadeOut var(--animation-duration) forwards;
}
.turn-page.turn > div.back-page {
animation: fadeIn var(--animation-duration) forwards;
}
/* 淡出动画 */
@keyframes fadeOut {
0% {
visibility: visible;
}
49% {
visibility: visible;
}
50% {
visibility: hidden;
}
100% {
visibility: hidden;
}
}
/* 淡入动画 */
@keyframes fadeIn {
0% {
visibility: hidden;
}
50% {
visibility: hidden;
}
51% {
visibility: visible;
}
100% {
visibility: visible;
}
}
翻页动画
@keyframes turnForward {
0% {
z-index: 999;
}
40% {
z-index: 999;
}
49% {
transform: rotateY(-90deg);
}
50% {
transform: rotateY(-90deg);
}
100% {
transform: rotateY(-180deg);
z-index: null;
}
}
@keyframes turnBackward {
0% {
z-index: 999;
}
40% {
z-index: 999;
}
49% {
transform: rotateY(-90deg);
}
50% {
transform: rotateY(-90deg);
}
100% {
transform: rotateY(0deg);
z-index: null;
}
}
源码
gitee
github
- 🌟 觉得有帮助的可以点个 star~
- 🖊 有什么问题或错误可以指出,欢迎 pr~
- 📬 有什么想要实现的功能或想法可以联系我~
公众号
关注公众号『 前端也能这么有趣 』,获取更多有趣内容。
发送 加群 还可以加入群聊,一起来学习(摸鱼)吧~
说在后面
🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『
前端也能这么有趣
』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。