前言
直播系统app打开一个页面时,有时会看到这么一种动画:当前页的某些元素跳到下一个页面上。
那么直播系统网页端有没有办法实现这种类似于直播系统app端页面切换的动画效果呢?经过探索,发现谷歌浏览器已经提供了这么一个实验性API:
documentTransition
它是一种新的脚本API的提议,允许在单页应用程序(SPA)和多页应用程序(MPAs)中使用一组简单的过渡动画。这个特性的灵感来自于Material Design原则中列出的过渡。其目的是支持类似于Android Activity transitions的过渡动画效果。
浏览器开启该功能API
由于该特性是实验功能,需要手动开启。在浏览器中输入
chrome://flags/#document-transition
然后将documentTransition设置为Enabled启用。
设置完之后我们重启下浏览器,然后打开控制台输入:
'documentTransition' in document
结果打印为true的话,说明我们浏览器已经成功开启该实验功能API。
如何理解该API
该API提案可以分为两部分:根转换(root transition)和共享元素转换(shared element transition)。
根转换(root transition)
根转换可以理解为直播系统"页面“在载入时的动画过渡效果,如直播系统iOS端点击跳转下一个页面时,下一个页面是从右到左推入的。下面代码实现该效果(注意:效果跟直播系统APP差异较大,总体效果是能看出“页面”是从右到左推入的,请自行运行代码在浏览器中查看效果):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>rootTransition示例</title>
</head>
<style>
.list {
height: 100vh;
}
.details {
height: 100vh;
background-color: aquamarine;
}
.hide {
display: none;
}
</style>
<body>
<div class="list">
列表页
<button id="btn">点击去详情页</button>
</div>
<div class="details hide">详情页</div>
<script>
const btn = document.querySelector('#btn')
const details = document.querySelector('.details')
const list = document.querySelector('.list')
btn.addEventListener('click', () => {
navigateToDetailsPage()
})
async function navigateToDetailsPage() {
await document.documentTransition.prepare({
rootTransition: "cover-left",
});
details.classList.remove('hide')
list.classList.add('hide')
document.documentTransition.start();
}
</script>
</body>
</html>
以上就是一个root transition的例子,它的使用模型可以概括如下:
// 用户点击按钮切换页面时执行
async function navigateToSettingsPage() {
// 捕捉当前页面状态,进行动画准备
await document.documentTransition.prepare({
rootTransition: 'cover-left', // “页面”切换效果
});
// 执行更新DOM操作,显示下一页的内容
updateDOMForNextPage();
// 调用start开始执行动画
await document.documentTransition.start();
// 动画结束
}
支持的动画效果
rootTransition支持以下属性:
- reveal-left: 旧内容从中心向指定方向滑动,显示新内容。
- reveal-right
- reveal-up
- reveal-down
- cover-left: 新内容沿指定方向从边缘滑动,覆盖旧内容。
- cover-right
- cover-up
- cover-down
- explode: 旧内容通过成长和变得更加透明而“爆炸”,并揭示出新的内容。
- implode: 新内容会“内爆”,从大的一面收缩,变得不透明,转换旧内容。
共享元素转换(shared element transition)
共享元素就是用户头像及名字,可以看到这两个元素从直播系统当前页到下一页加载完时是一直处于可视状态的,并且从直播系统当前页显示位置大小到下一页显示位置大小有一个平滑过渡的效果。
如何使用shared element
async function navigateToSettingsPage() {
await document.documentTransition.prepare({
rootTransition: 'cover-up',
sharedElements: [element1, element2, element3],
});
// updateDOM
await document.documentTransition.start({
sharedElements: [element1, element4, element5],
});
}
sharedElements是一个数组,里面存放“跨页”共享的元素,对应动图的例子来说就是存放用户的头像及名字的dom。
需要注意的是:
1、在prepare及start方法中都要设置sharedElements属性,并且是一一对应的关系。例如element2在切换到“下一页”时,对应过渡到的就是element4所在位置。
2、需要配合css的contain属性才能正常工作,通常设置为contain: paint;该属性的作用是如果一个元素在视窗外或因其他原因导致不可见,则同样保证它的子孙节点不会被显示。详见:contain
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>rootTransition示例</title>
</head>
<style>
body{margin:0}.flex-center{display:flex;align-items:center;justify-content:center}.list{height:100vh}.details{height:100vh}.hide{display:none!important}.card{display:flex;align-items:center;margin:0 20px;box-shadow:0 0 50px #ccc;border-radius:12px;overflow:hidden}.card .desc{font-size:18px;color:#333;font-weight:bold;margin-left:20px}.details-desc{font-size:22px;color:limegreen}.list{display:flex;flex-direction:column;justify-content:center}.button-wrap{margin-top:20px;text-align:center}.back-btn{display:inline-block;width:100px;height:40px}.details-cover{display:block;width:100%}.details-desc{position:absolute;right:20px;top:20px}.cover,.details-cover,.desc,.details-desc{contain:paint}
</style>
<body>
<div class="list">
<div class="card">
<img class="cover"
src="http://p1-q.mafengwo.net/s18/M00/52/27/CoUBYGDMNO-AOlK4AAVHKFDW8_Y808.jpg?imageMogr2%2Fthumbnail%2F%21220x150r%2Fstrip%2Fgravity%2FCenter%2Fcrop%2F%21220x150%2Fquality%2F90" />
<span class="desc">人生海海</span>
</div>
<div class="button-wrap">
<button id="btn">点击去详情页</button>
</div>
</div>
<div class="details hide">
<div>
<div style="position: relative;">
<img class="details-cover"
src="http://p1-q.mafengwo.net/s18/M00/52/27/CoUBYGDMNO-AOlK4AAVHKFDW8_Y808.jpg?imageMogr2%2Fthumbnail%2F%21220x150r%2Fstrip%2Fgravity%2FCenter%2Fcrop%2F%21220x150%2Fquality%2F90" />
<div class="details-desc">人生海海</div>
</div>
<div class="button-wrap">
<button class="back-btn">返回</button>
</div>
</div>
</div>
<script>
const btn = document.querySelector('#btn')
const details = document.querySelector('.details')
const list = document.querySelector('.list')
const backBtn = document.querySelector('.back-btn')
const cover = document.querySelector('.cover')
const desc = document.querySelector('.desc')
const detailsCover = document.querySelector('.details-cover')
const detailsDesc = document.querySelector('.details-desc')
btn.addEventListener('click', () => {
navigateToDetailsPage()
}, false)
backBtn.addEventListener('click', () => {
showList()
}, false)
async function navigateToDetailsPage() {
await document.documentTransition.prepare({
rootTransition: "cover-up",
sharedElements: [
cover,
desc
]
});
details.classList.remove('hide')
list.classList.add('hide')
document.documentTransition.start({
sharedElements: [
detailsCover,
detailsDesc
]
});
}
async function showList() {
await document.documentTransition.prepare({
rootTransition: "implode",
sharedElements: [
detailsCover,
detailsDesc
]
});
details.classList.add("hide");
list.classList.remove("hide");
await document.documentTransition.start({
sharedElements: [
cover,
desc
]
});
}
</script>
</body>
</html>
以上就是“直播系统网页如何实现类似app的页面切换动画?”的全部内容,在直播哦系统开发时需要我们注意的细节点有很多,希望以上内容能对大家有帮助。