完整代码
<template>
<div class="dockBox">
<div class="glass">
<ul class="dock">
<li>😃</li>
<li>😊</li>
<li>😜</li>
<li>😍</li>
<li>🤩</li>
<li>🥳</li>
<li>🥶</li>
<li>😃</li>
<li>😊</li>
<li>😜</li>
<li>😍</li>
<li>🤩</li>
<li>🥳</li>
<li>🥶</li>
</ul>
</div>
</div>
</template>
<script lang="ts" setup>
import { defineComponent, ref } from "vue";
function resetScale() {
document.querySelectorAll(".dock li").forEach((li) => {
li.style.setProperty("--scale", 1);
});
}
onMounted(() => {
document.querySelectorAll(".dock li").forEach((li) => {
li.addEventListener("click", (e) => {
e.currentTarget.classList.add("loading");
});
li.addEventListener("mousemove", (e) => {
// 当事件被触发时,获取目标元素
let item = e.target;
// 获取目标元素的矩形信息
let itemRect = item.getBoundingClientRect();
// 计算鼠标指针在目标元素内的偏移量
let offset = Math.abs(e.clientX - itemRect.left) / itemRect.width;
// 获取目标元素的前一个兄弟元素(如果存在)
let prev = item.previousElementSibling || null;
// 获取目标元素的后一个兄弟元素(如果存在)
let next = item.nextElementSibling || null;
// 设置缩放的基准比例
let scale = 0.6;
// 重置所有元素的缩放比例
resetScale();
// 如果前一个元素存在,根据偏移量调整其缩放比例
if (prev) {
prev.style.setProperty("--scale", 1 + scale * Math.abs(offset - 1));
}
// 设置当前元素的缩放比例
item.style.setProperty("--scale", 1 + scale);
// 如果后一个元素存在,根据偏移量调整其缩放比例
if (next) {
next.style.setProperty("--scale", 1 + scale * offset);
}
});
});
document.querySelector(".dock").addEventListener("mouseleave", (e) => {
resetScale();
});
});
</script>
<style scoped>
html {
font-size: 15px;
}
.dockBox {
margin: 0;
padding: 0;
display: flex;
width: 100%;
min-height: 100vh;
overflow: hidden;
align-items: flex-end;
background-image: linear-gradient(
109.6deg,
rgba(25, 170, 209, 1) 11.3%,
rgba(21, 65, 249, 1) 69.9%
);
}
.glass {
width: 100%;
height: 8rem;
background: rgba(255, 255, 255, 0.25);
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
border: 1px solid rgba(255, 255, 255, 0.18);
display: flex;
justify-content: center;
}
.dock {
--scale: 1;
list-style: none;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
}
.dock li {
font-size: calc(6rem * var(--scale));
padding: 0 0.5rem;
cursor: default;
position: relative;
top: calc((6rem * var(--scale) - 6rem) / 2 * -1);
transition: 15ms all ease-out;
}
.dock li.loading {
animation: 1s loading ease-in infinite;
}
@keyframes loading {
0%,
100% {
transform: translateY(0px);
}
60% {
transform: translateY(-40px);
}
}
</style>
原理就是监听鼠标的移入移除,给鼠标位置、鼠标的前后元素进行设置一个scale,以及添加动画过度