前言
-
最近在写PC端的业主端时候,发现传统的菜单栏比较丑,也不符合实际应用(功能页面并不多-展示为主)
-
偶然发现钉钉官网的效果挺有意思的,想着把这个效果复原过来,然后夸夸搜索了一番。
-
经过一顿的cv打法,加上修修补补把大概的效果整了出来,时间关系最基础的,剩下的可以自己补充
地址演示:演示效果地址
视频效果
官网效果
细节
1.代码中第二屏是300vh是3倍,试过很多遍,3倍滚动时效果最好不建议改,建议不显示滚动条(src/styles/index.scss)效果最好
::-webkit-scrollbar {
// 隐藏滚动条
display: none; /* Chrome Safari */
}
2.代码中第二屏的3个class类名最好不要改,因为是根据这几个类名在获取DOM操作
3.代码中第二屏中 list-itme中的data-order="0"等于几(从0开始)控制动画盒子顺序,可以自己调试看效果
完整代码-可复制
<template>
<div class="conter">
<!-- 第一屏 -->
<div class="flatly-itemone">
</div>
<!-- 第二屏 -->
<div class="playground">
<div class="animation-container">
<div class="titlemanifesto" v-if="titlemanifesto">
生活意义-坦然面对生活并且接受她的事与愿违
</div>
<!-- data-order="0" 数字是控制每一项动画顺序 -->
<div class="list">
<div data-order="0" class="list-item"></div>
<div data-order="1" class="list-item"></div>
<div data-order="2" class="list-item"></div>
<div data-order="2" class="list-item"></div>
<div data-order="1" class="list-item"></div>
<div data-order="0" class="list-item"></div>
<div data-order="0" class="list-item"></div>
<div data-order="1" class="list-item"></div>
<div data-order="2" class="list-item"></div>
<div data-order="2" class="list-item"></div>
<div data-order="1" class="list-item"></div>
<div data-order="0" class="list-item"></div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Dashboard',
data() {
return {
animataionMap: new Map(),
// 文字显示
titlemanifesto: false
}
},
created() {},
mounted() {
this.updateMap(),
this.updateStyle(),
window.addEventListener('scroll', this.updateStyle)
},
methods: {
// 得出动画节点数值
createAnimation(scrollStart, scrollEnd, valueStart, valueEnd) {
return (scroll) => {
if (scroll <= scrollStart) {
return valueStart
}
if (scroll >= scrollEnd) {
return valueEnd
}
return (
valueStart +
((valueEnd - valueStart) * (scroll - scrollStart)) /
(scrollEnd - scrollStart)
)
}
},
getDomAnimation(scrollStart, scrollEnd, dom) {
const list = document.querySelector('.list')
scrollStart = scrollStart + dom.dataset.order * 300
const opacityAnimation = this.createAnimation(
scrollStart,
scrollEnd,
0,
1
)
// 基于当前滚动计算得出的透明度
const opacity = function (scroll) {
return opacityAnimation(scroll)
}
const scaleAnimation = this.createAnimation(
scrollStart,
scrollEnd,
0.3,
1
)
const xAnimation = this.createAnimation(
scrollStart,
scrollEnd,
list.clientWidth / 2 - dom.offsetLeft - dom.clientWidth / 2,
0
)
const yAnimation = this.createAnimation(
scrollStart,
scrollEnd,
list.clientHeight / 2 - dom.offsetTop - dom.clientHeight / 2,
0
)
const transform = function (scroll) {
return `translate(${xAnimation(scroll)}px,${yAnimation(
scroll
)}px) scale(${scaleAnimation(scroll)})`
}
return {
opacity,
transform
}
},
updateMap() {
const items = document.querySelectorAll('.list-item')
const playGround = document.querySelector('.playground')
this.animataionMap.clear()
const playGroundRect = playGround.getBoundingClientRect()
// 开始动画的距离
const scrollStart = playGroundRect.top + window.scrollY
// 结束动画的距离 相当于playground的高度
const scrollEnd =
playGroundRect.bottom + window.scrollY - window.innerHeight
for (const item of items) {
this.animataionMap.set(
item,
this.getDomAnimation(scrollStart, scrollEnd, item)
)
}
// 打开遮罩层
// this.listmsk = true
},
updateStyle() {
const scroll = window.scrollY
// 获取元素-改变背景颜色
const list = document.querySelector('.list')
if (scroll > 2200 && scroll < 2862) {
console.log('打开遮罩层')
list.style.backgroundColor = 'rgba(23, 26, 29, 0.9)'
// 显示文字
this.titlemanifesto = true;
} else {
console.log('关闭遮罩层')
list.style.backgroundColor = '#063868'
// 隐藏文字
this.titlemanifesto = false
}
console.log('scroll', scroll)
for (let [dom, value] of this.animataionMap) {
for (const cssProp in value) {
dom.style[cssProp] = value[cssProp](scroll)
}
}
}
}
}
</script>
<style lang="scss" scoped>
.conter {
.flatly-itemone {
height: 90vh;
background-color: #fff;
}
.playground {
height: 310vh;
background-color: #063868;
position: relative;
.animation-container {
display: flex;
position: sticky;
top: 0;
height: 100vh;
text {
z-index: 999;
color: red;
}
// 标题
.titlemanifesto {
height: 50px;
width: 1000px;
position: absolute;
left: 50%;
top: 23%;
transform: translate(-50%);
// background-color: skyblue;
text-align: center;
color: #fff;
font-family: PingFangSC-Medium;
font-weight: 500;
font-size: 30px;
line-height: 50px;
}
.list {
height: 550px;
width: 1000px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -28%);
display: flex;
flex-wrap: wrap;
align-items: center;
border-radius: 10px;
padding: 15px 20px;
opacity: 0.8;
.list-item {
width: 100px;
height: 155px;
border-radius: 10px;
background-color: #fff;
margin: 50px 30px;
&:nth-child(2n - 1) {
background-color: skyblue;
}
&:nth-child(2n) {
background-color: rgb(111, 245, 111);
}
&:nth-child(3n) {
background-color: orange;
}
}
}
}
}
}
</style>
总结:
经过这一趟流程下来相信你也对 vue 实现钉钉官网的轮播图下面功能滚动排版CSS效果 有了初步的深刻印象,但在实际开发中我 们遇到的情况肯定是不一样的,所以我们要理解它的原理,万变不离其宗。加油,打工人!
什么不足的地方请大家指出谢谢 -- 風过无痕