弹跳弹跳,弹跳鱼尾纹弹出菜单(vue)
时间:2023-04-02 18:19:14
HTML
前言之前采访的总结,大家看了还行,因为量大,错误在所难免,希望大家找到后告诉我错误,我的邮箱是236490794@qq.com,一个前端的小希望。言归正传,我们照例直接上传效果图,然后开始分享这个项目的github。可以看看组件分析界面组成逻辑分析,最终实现界面组成。从上图我们可以看出界面主要分为menu和item2块。其中,menu的动画是自传,item的动画是位移。那么这里我们通过绝对布局的方式将整个控件定位在四个角上。menu_container{位置:绝对;z-指数:100;边界半径:50%;过渡持续时间:400ms;文本对齐:居中;边框:#efefef3px实心;盒子阴影:aliceblue1px1px1px;}.menu_item{位置:绝对;边界半径:50%;z-指数:99;#efefef3px实心;文本对齐:居中;盒子阴影:aliceblue1px1px1px;}逻辑分析这里我把这个控件的几个属性分离出来,方便接下来的开发,包括菜单的背景,整个控件在屏幕上菜单的角,菜单的宽高,item和item之间的距离菜单的位移、菜单的背景色、item的背景色、item的相关内容都是由数据控制的。我们将在下面的实现中直接说明。最后我用代码加上注释帮助大家理解。我只是拿了模板
通过分析核心实现可以得出每个item的偏移量应该是水平x:基本值*sin(角度值)垂直y:基本值*cos(角度值)角度值:(数组长度-1-当前下标)每块占的角度用弧度表示:2*Math.PI/exportdefault{...props:{//开启属性,方便自定义menuSrc:{default:require('../assets/menu.png')},position:{default:'LT'//可选LT,LB,RT,RB4角},宽度:{默认值:50,},baseDistance:{默认值:150,},menuBg:{默认值:'white'},itemBg:{默认值:'white'},menuItems:{类型:Array,}},data(){return{openFlag:false,//展开合并标志运算符:['+','+'],//展开时用于记录动画XY方向}},mounted(){//根据props初始化每个内容的各种样式this.$refs.menuHome.style.width=this.width+'px';this.$refs.menuHome.style.height=this.width+'px';this.$refs.menuHome.style.lineHeight=this.width+'px';this.$refs.menuHome.style.background=this.menuBg;this.menuItems.forEach((item)=>{letel=document.getElementById(item.name);el.style.width=`${this.width*0.8}px`;el.style.height=`${this.width*0.8}px`;el.style.lineHeight=`${this.width*0.8}px`;el.style.background=this.itemBg;});//根据位置,选择不同的位置开关(this.position){case'LT':this.$refs.menuHome.style.left='20px';this.$refs.menuHome.style.top='20px';this.menuItems.forEach((item)=>{letel=document.getElementById(item.name);el.style.left='26px';el.style.top='26px';});这个.operators=['+','+'];休息;...}},methods:{toggleMenu(){if(!this.openFlag){//合并时,点击展开操作this.menuItems.forEach((item,index)=>{this.toggleMenuTransition(item.name,index,false)});//菜单本身围绕this.$refs.menuHome.style.transform='rotate(度)';}else{this.menuItems.forEach((item,index)=>{this.toggleMenuTransition(item.name,index,true)});//菜单恢复this.$refs.menuHome.style.transform='rotate(0)';}this.openFlag=!this.openFlag;},toggleMenuTransition(name,index,revert){letoneArea=90/(this.menuItems.length-1);//每个块占用的角度letaxisX=Math.sin((this.menuItems.length-1-index)*oneArea*2*Math.PI/360);//横坐标偏移的比例letaxisY=Math.cos((this.menuItems.length-1-index)*oneArea*2*Math.PI/360);//纵坐标比较便宜的比例letel=document.getElementById(name);//如果传入的名字相同,会报错。让那个=这个;if(!revert){setTimeout(function(){el.style.transitionDuration='200ms';el.style.transform=`translate(${that.operators[0]}${that.baseDistance*axisX}px,${that.operators[1]}${that.baseDistance*axisY}px)`;//Animate},index*100)//通过定时器的方式,实现一一弹出的效果}else{//项目恢复el.style.transitionDuration='200ms';el.style.transform=`translate(0,0)`;}},clickMenu(item,index){//暴露方法给父组件,执行点击事件操作this.$emit('clickMenu',item,index)}}}并导入到父组件中,重做。让我们跳一会儿,燃烧你的卡路里。父组件调用引入的组件importtoggleMenufrom'./toggleMenu'在components中声明组件:{toggleMenu},在template中使用menuItems:[//name和src是必须的,name是唯一的,否则会报错{name:'menu1',src:require('../assets/emoji.png')},{name:'menu2',src:require('../assets/cart.png')},{name:'menu3',src:require('../assets/folder.png')},{name:'menu4',src:require('../assets/home.png')},{name:'menu5',src:require('../assets/my.png')},]
属性和方法一列属性名使用默认值必须定位四个位置(LT,LB,RT,RB)LTnomenuBg菜单背景白色nomenuSrc菜单图片a菜单图片noitemBg按钮背景白色nowidth按钮宽度50pxnobaseDistance位移距离,如果项目较多,可适当增加150px。没有menuItems菜单数组是没有用的。参数clickMenu点击item触发事件item和index。几乎是共享的。