cubic-bezier即三次贝塞尔,可以生成贝塞尔曲线,在css中主要是给transition以及animation提供过渡效果的速度曲线
cubic-bezier函数默认接受四个参数,cubic-bezier(x1,y1,x2,y2),其中y1、y2是可以大于或小于0的,基于此可以做出一些缓冲的过渡效果
<template> <div class="menu"> <div v-for="item in menuList"> <div class="menu-item" @mouseover="mouseover($event, item)" @mouseleave="mouseleave">{{ item.name }}</div> </div> </div> <transition name="move"> <div id="sub-menu" ref="subMenu" v-show="show" @mousemove="overSub"> <div class="sub-menu-item" v-for="item in subMenuList"> {{ item.name }} </div> </div> </transition> </template> <script> import { ref } from 'vue'; export default { setup() { let menuList = ref([ { name: 'cloud', children: [ { name: 'cloud1' }, { name: 'cloud2' } ] }, { name: 'software', children: [ { name: 'software1' }, { name: 'software2' }, { name: 'software3' } ] }, { name: 'docs', children: [ { name: 'docs1' }, { name: 'docs2' } ] } ]); let subMenuList = ref([]); let show = ref(false); return { menuList, subMenuList, show }; }, methods: { mouseover(e, item) { this.subMenuList = item.children; this.$refs.subMenu.style.left = e.target.offsetLeft + 'px'; this.$refs.subMenu.style.height = `${43 * this.subMenuList.length}px`; this.show = true; }, mouseleave() { this.show = false; } } }; </script> <style scoped> .menu { display: flex; } .menu-item { height: 40px; fit-content; margin-left: 20px; font-size: 26px; font-weight: lighter; color: #aaa; cursor: pointer; } #sub-menu { position: absolute; font-size: 32px; font-weight: lighter; color: #000; border: solid 1px #ccc; padding: 15px; border-radius: 10px; } .move-enter-active, .move-leave-active { transition: all 0.3s cubic-bezier(0.175, 0.585, 0.32, 1.275); } </style>
没有用原生的transition属性是因为v-if不支持,所以必须结合vue的transition组件
其中 cubic-bezier(0.175, 0.885, 0.32, 1.275); 是提供过渡效果的关键,可以看出整个菜单会有一个缓冲的过渡效果,视觉上也更加具有冲击力
补充一个html版本,可以直接打开看效果
<body> <div class="menu"> <div class="menu-item">cloud</div> <div class="menu-item">software</div> <div class="menu-item">docs</div> </div> <div id="sub-menu"> <div class="sub-menu-item">cloud1</div> <div class="sub-menu-item">cloud2</div> </div> <script> (function () { let menu = document.getElementsByClassName('menu-item'); let subMenu = document.getElementById('sub-menu'); for (let item of menu) { item.addEventListener('mouseover', function () { subMenu.style.visibility = 'visible'; subMenu.style.left = item.offsetLeft; }); item.addEventListener('mouseleave', function () { subMenu.style.visibility = 'hidden'; }); } })(); </script> </body> <style> .menu { display: flex; } .menu-item { height: 40px; width: fit-content; margin-left: 20px; font-size: 26px; font-weight: lighter; color: #aaa; cursor: pointer; } #sub-menu { visibility: hidden; position: absolute; font-size: 32px; font-weight: lighter; color: #000; border: solid 1px #ccc; padding: 15px; border-radius: 10px; transition: all 0.35s cubic-bezier(0.175, 0.585, 0.32, 1.275); } </style>