Vue弹出菜单功能的实现代码


Posted in Javascript onSeptember 12, 2018

言归正传

我们老样子直接先上效果图再开始今天的分享 这个项目的github可以看一看

Vue弹出菜单功能的实现代码

组件分析

  1. 界面组成
  2. 逻辑分析
  3. 最终实现

界面组成

从上图中,我们可以看出界面主要分为menu和item2块,其中menu的动画是自传,item的动画是位移,然后这里我们通过绝对布局的方式将整个控件定位在四个角落

.menu_container {
  position: absolute;
  z-index: 100;
  border-radius: 50%;
  transition-duration: 400ms;
  text-align: center;
  border: #efefef 3px solid;
  box-shadow: aliceblue 1px 1px 1px;
 }

 .menu_item {
  position: absolute;
  border-radius: 50%;
  z-index: 99;
  border: #efefef 3px solid;
  text-align: center;
  box-shadow: aliceblue 1px 1px 1px;
 }

逻辑分析

这里我将这个控件几个属性独立出来,方便下次开发,其中包含,menu的背景,整个控件在屏幕的哪个角落,menu的宽高,item距离menu位移的距离,menu的背景色,及item的背景色,item的相关内容则由数据来控制,具体的我们直接在下方的实现里来讲解。

最终实现

这里我用代码加注释的方式,帮助大家理解,template我简单的带过一下

<div>
  <div class="menu_container" ref="menuHome" @click="toggleMenu">
   <img :src="menuSrc"><!--menu图-->
  </div>
  <div class="menu_item" v-for="(item,index) in menuItems" :id="item.name" @click="clickMenu(item,index)">
   <img :src="item.src"><!--item图-->
  </div>
 </div>

核心实现 通过分析可以得出,每个item的偏移量应该为 横向x:基础值 * sin(角度值) 纵向y:基础值 * cos(角度值) 角度值:(数组的长度-1-当前的下标)* 每一块所占的角度 * 弧度表示 弧度表示:2 * Math.PI / 360

export default {
  ...
  props: {//开放的属性,方便自定义
   menuSrc: {
    default: require('../assets/menu.png')
   },
   position: {
    default: 'LT'//可选择LT、LB、RT、RB4个角落
   },
   width: {
    default: 50,
   },
   baseDistance: {
    default: 150,
   },
   menuBg: {
    default: 'white'
   },
   itemBg: {
    default: 'white'
   },
   menuItems: {
    type: Array,
   }
  },
  data() {
   return {
    openFlag: false,//展开合并标志
    operators: ['+', '+'],//用于记录展开时动画XY方向
   }
  },
  mounted() {
   //根据props初始化各内容的各种style
   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) => {
    let el = 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;
   });
   //根据position,选择不同的定位
   switch (this.position) {
    case 'LT':
     this.$refs.menuHome.style.left = '20px';
     this.$refs.menuHome.style.top = '20px';
     this.menuItems.forEach((item) => {
      let el = document.getElementById(item.name);
      el.style.left = '26px';
      el.style.top = '26px';

     });
     this.operators = ['+', '+'];
     break;
    ...
   }
  },
  methods: {
   toggleMenu() {
    if (!this.openFlag) {//合并时,点击展开操作
     this.menuItems.forEach((item, index) => {
      this.toggleMenuTransition(item.name, index, false)
     });
     //menu本身转一周
     this.$refs.menuHome.style.transform = 'rotate(360deg)';
    } else {
     this.menuItems.forEach((item, index) => {
      this.toggleMenuTransition(item.name, index, true)
     });
     //menu恢复
     this.$refs.menuHome.style.transform = 'rotate(0)';
    }
    this.openFlag = !this.openFlag;
   },
   toggleMenuTransition(name, index, revert) {
    let oneArea = 90 / (this.menuItems.length - 1);//每一块所占的角度
    let axisX = Math.sin((this.menuItems.length - 1 - index) * oneArea * 2 * Math.PI / 360);//横坐标所偏移的比例
    let axisY = Math.cos((this.menuItems.length - 1 - index) * oneArea * 2 * Math.PI / 360);//纵坐标所便宜的比例
    let el = document.getElementById(name);//若所传的name一直,会报错。
    let that = this;
    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)`;//进行动画
     }, index * 100)//通过定时器的方式,达到一个一个弹出来的效果
    } else {
     //item恢复
     el.style.transitionDuration = '200ms';
     el.style.transform = `translate(0,0)`;
    }
   },
   clickMenu(item, index) {
    //暴露方法给父组件,进行点击事件的操作
    this.$emit('clickMenu', item, index)
   }
  }
 }

再父组件中引入就可以大功告成啦,先跳一会儿吧,燃烧你的卡路里

父组件调用

引入组件

import toggleMenu from './toggleMenu'

在 components声明

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')},
]
<toggle-menu :menuItems="menuItems"
       @clickMenu="clickMenu"
       ></toggle-menu>

属性及方法一栏

属性名 用处 默认值 是否必须
position 四个方位(LT、LB、RT、RB) LT
menuBg 菜单背景 white
menuSrc 菜单图片 一个菜单图片
itemBg 按钮背景 white
width 按钮宽度 50px
baseDistance 位移距离,若item很多,可适当提高 150px
menuItems 菜单数组
方法名 用处 参数
clickMenu 点击item触发事件 item,index

总结

以上所述是小编给大家介绍的Vue左侧底部弹出菜单功能的实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
讲两件事:1.this指针的用法小探. 2.ie的attachEvent和firefox的addEventListener在事件处理上的区别
Apr 12 Javascript
jquery事件机制扩展插件 jquery鼠标右键事件。
Dec 26 Javascript
完美兼容各大浏览器的jQuery仿新浪图文淡入淡出间歇滚动特效
Nov 12 Javascript
jQuery实现在最后一个元素之前插入新元素的方法
Jul 18 Javascript
KnockoutJS 3.X API 第四章之事件event绑定
Oct 10 Javascript
浅谈js的异步执行
Oct 18 Javascript
PHP获取当前页面完整URL的方法
Dec 02 Javascript
JavaScript中无法通过div.style.left获取值的解决方法
Feb 19 Javascript
ES6中Array.copyWithin()函数的用法实例详解
Sep 16 Javascript
Vue中的作用域CSS和CSS模块的区别
Oct 09 Javascript
Angular4.0动画操作实例详解
May 10 Javascript
design vue 表格开启列排序的操作
Oct 28 Javascript
angular4中*ngFor不能对返回来的对象进行循环的解决方法
Sep 12 #Javascript
详解SPA中前端路由基本原理与实现方式
Sep 12 #Javascript
对angular2中的ngfor和ngif指令嵌套实例讲解
Sep 12 #Javascript
vue-cli 使用axios的操作方法及整合axios的多种方法
Sep 12 #Javascript
Vue $emit $refs子父组件间方法的调用实例
Sep 12 #Javascript
bootstrap table表格插件之服务器端分页实例代码
Sep 12 #Javascript
详解html-webpack-plugin插件(用法总结)
Sep 12 #Javascript
You might like
php下几个常用的去空、分组、调试数组函数
2009/02/22 PHP
PHP编程最快明白(第一讲 软件环境和准备工作)
2010/10/25 PHP
PHP数组传递是值传递而非引用传递概念纠正
2013/01/31 PHP
php去除字符串换行符示例分享
2014/02/13 PHP
destoon整合ucenter后注册页面不跳转的解决方法
2014/06/21 PHP
php模拟post提交数据的方法
2015/02/12 PHP
Javascript和Ajax中文乱码吐血版解决方案
2009/12/21 Javascript
JavaScript实现页面5秒后自动跳转的方法
2015/04/16 Javascript
js仿3366小游戏选字游戏
2016/04/14 Javascript
AngularJS 路由详解和简单实例
2016/07/28 Javascript
NodeJS使用formidable实现文件上传
2016/10/27 NodeJs
JS文件/图片从电脑里面拖拽到浏览器上传文件/图片
2017/03/08 Javascript
jQuery自定义多选下拉框效果
2017/06/19 jQuery
JavaScript变量类型以及变量作用域详解
2017/08/14 Javascript
2种在vue项目中使用百度地图的简单方法
2018/09/28 Javascript
vue实现element表格里表头信息提示功能(推荐)
2019/11/20 Javascript
vantUI 获得piker选中值的自定义ID操作
2020/11/04 Javascript
Vue实现省市区三级联动
2020/12/27 Vue.js
Node快速切换版本、版本回退(降级)、版本更新(升级)
2021/01/07 Javascript
js实现电灯开关效果
2021/01/19 Javascript
Python数据类型详解(二)列表
2016/05/08 Python
python通过cookie模拟已登录状态的初步研究
2016/11/09 Python
使用pandas对两个dataframe进行join的实例
2018/06/08 Python
python3实现zabbix告警推送钉钉的示例
2019/02/20 Python
Python的Lambda函数用法详解
2019/09/03 Python
selenium框架中driver.close()和driver.quit()关闭浏览器
2020/12/08 Python
python实现定时发送邮件到指定邮箱
2020/12/23 Python
CSS3 边框效果
2019/11/04 HTML / CSS
澳大利亚购买太阳镜和眼镜网站:Glamoureyes
2020/09/22 全球购物
小学生寒假家长评语
2014/04/16 职场文书
环保建议书300字
2014/05/14 职场文书
餐饮周年庆活动方案
2014/08/14 职场文书
2014最新预备党员思想汇报范文:中国梦,我的梦
2014/10/25 职场文书
学校群众路线专项整治方案
2014/10/31 职场文书
正规欠条模板
2015/07/03 职场文书
使用Python获取字典键对应值的方法
2022/04/26 Python