序文
-
最近、PC 側のオーナー側の記事を書いているときに、従来のメニュー バーが見苦しく、実際のアプリケーションを満たしていないことがわかりました (機能的なページがあまりなく、表示がメインです)。
-
DingTalk公式サイトのエフェクトが面白いことを偶然発見したので、このエフェクトを復活させようと思い検索してみました。
-
しばらくCVをプレイし、さらにいじくり回した後、全体的な効果を調整しました。時間の関係は最も基本的なもので、残りは自分で補うことができます。
ビデオエフェクト
公式サイト効果
詳細
1. コードの 2 番目の画面は 300vh で、3 倍です。何度も試しましたが、3 倍のスクロールが最も効果的です。変更することはお勧めしません。スクロールを表示しないことをお勧めします。最良の効果を得るには、バー (src/styles/index.scss)
::-webkit-scrollbar {
// 隐藏滚动条
display: none; /* Chrome Safari */
}
2. DOM 操作はこれらのクラス名に基づいて取得されるため、コードの 2 番目の画面にある 3 つのクラス名は変更しないことをお勧めします。
3. コードの 2 番目の画面の 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>
要約:
このプロセスを経て、DingTalk の公式 Web サイトのカルーセル チャートの下に Vue によるスクロール植字 CSS 効果の実装についての予備的な印象が深くなったと思いますが、実際の開発で遭遇する状況は決定的に異なるため、その原理を理解するにはすべてが変わります。 。さあ、労働者を殴ってください!
不備があればご指摘ください、ありがとうございます -- Fengguowuhen