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 相关文章推荐
JavaScript 对话框和状态栏使用说明
Oct 25 Javascript
jQuery 判断元素上是否绑定了事件
Oct 28 Javascript
jQuery中attr()和prop()在修改checked属性时的区别
Jul 18 Javascript
JS简单模拟触发按钮点击功能的方法
Nov 30 Javascript
js获取元素的标签名实现方法
Oct 08 Javascript
浅谈javascript中的事件冒泡和事件捕获
Dec 28 Javascript
JavaScript实现二分查找实例代码
Feb 22 Javascript
jquery.validate表单验证插件使用详解
Jun 21 jQuery
nuxt.js 缓存实践
Jun 25 Javascript
JS在Array数组中按指定位置删除或添加元素对象方法示例
Nov 19 Javascript
JavaScript随机数的组合问题案例分析
May 16 Javascript
JS函数式编程实现XDM一
Jun 16 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
微信开发之获取JSAPI TICKET
2017/07/07 PHP
phpStudy配置多站点多域名方法及遇到的403错误解决方法
2017/10/19 PHP
jQuery ajax+PHP实现的级联下拉列表框功能示例
2019/02/12 PHP
jQuery选中select控件 无法设置selected的解决方法
2010/09/01 Javascript
Document对象内容集合(比较全)
2010/09/06 Javascript
广泛收集的jQuery拖放插件集合
2012/04/09 Javascript
解决jquery的datepicker的本地化以及Today问题
2012/05/23 Javascript
jQuery拖动div、移动div、弹出层实现原理及示例
2014/04/08 Javascript
一种新的javascript对象创建方式Object.create()
2015/12/28 Javascript
JavaScript Ajax实现异步通信
2016/12/14 Javascript
Node.js常用工具之util模块
2017/03/09 Javascript
jQuery Jsonp跨域模拟搜索引擎
2017/06/17 jQuery
ES6中Class类的静态方法实例小结
2017/10/28 Javascript
Bootstrap Table 双击、单击行获取该行及全表内容
2018/08/31 Javascript
JS编写兼容IE6,7,8浏览器无缝自动轮播
2018/10/12 Javascript
JS高阶函数原理与用法实例分析
2019/01/15 Javascript
使用p5.js临摹动态图形
2019/10/23 Javascript
Vue ElementUI实现:限制输入框只能输入正整数的问题
2020/07/31 Javascript
javascript canvas封装动态时钟
2020/09/30 Javascript
Python批量创建迅雷任务及创建多个文件
2016/02/13 Python
Django框架实现逆向解析url的方法
2018/07/04 Python
django利用request id便于定位及给日志加上request_id
2018/08/26 Python
对python中数组的del,remove,pop区别详解
2018/11/07 Python
Python面向对象程序设计OOP深入分析【构造函数,组合类,工具类等】
2019/01/05 Python
python实现日志按天分割
2019/07/22 Python
django-csrf使用和禁用方式
2020/03/13 Python
使用HTML5 Canvas绘制直线或折线等线条的方法讲解
2016/03/14 HTML / CSS
高清屏中使用Canvas绘图出现模糊的问题及解决方法
2019/06/03 HTML / CSS
日本PLST在线商店:日本时尚杂志刊载的人气服装
2016/12/10 全球购物
给领导的检讨书
2014/02/16 职场文书
人力资源主管的岗位职责
2014/03/15 职场文书
文艺演出策划方案
2014/06/07 职场文书
我爱祖国演讲稿
2014/09/02 职场文书
部门经理迟到检讨书
2015/02/16 职场文书
全家福照片寄语怎么写?
2019/04/02 职场文书
javascript之Object.assign()的痛点分析
2022/03/03 Javascript