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 相关文章推荐
json跟xml的对比分析
Jun 10 Javascript
javascript 实现简单的table排序及table操作练习
Dec 28 Javascript
jQuery登陆判断简单实现代码
Apr 21 Javascript
JavaScript创建类/对象的几种方式概述及实例
May 06 Javascript
Knockout text绑定DOM的使用方法
Nov 15 Javascript
学好js,这些js函数概念一定要知道【推荐】
Jan 19 Javascript
JavaWeb表单及时验证功能在输入后立即验证(含用户类型,性别,爱好...的验证)
Jun 09 Javascript
jQuery实现高级检索功能
May 28 jQuery
Vue混入mixins滚动触底的方法
Nov 22 Javascript
vue el-table实现自定义表头
Dec 11 Javascript
使用webpack5从0到1搭建一个react项目的实现步骤
Dec 16 Javascript
vue3引入highlight.js进行代码高亮的方法实例
Apr 08 Vue.js
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 的 __FILE__ 常量
2007/01/15 PHP
PHP数组循环操作详细介绍 附实例代码
2013/02/03 PHP
基于php无限分类的深入理解
2013/06/02 PHP
PHP使用json_encode函数时不转义中文的解决方法
2014/11/12 PHP
php基于 swoole 实现的异步处理任务功能示例
2019/08/13 PHP
PHP实现一个限制实例化次数的类示例
2019/09/16 PHP
laravel-admin自动生成模块,及相关基础配置方法
2019/10/08 PHP
Tips 带三角可关闭的文字提示
2010/10/06 Javascript
js返回上一页并刷新代码整理
2012/12/21 Javascript
简单的代码实现jquery定时器
2014/01/03 Javascript
js实现select组件的选择输入过滤代码
2014/10/14 Javascript
js实现点击向下展开的下拉菜单效果代码
2015/09/01 Javascript
iframe中使用jquery进行查找的方法【案例分析】
2016/06/17 Javascript
微信小程序 Storage API实例详解
2016/10/02 Javascript
js实现点击每个li节点,都弹出其文本值及修改
2016/12/15 Javascript
使用javaScript实现鼠标拖拽事件
2020/04/03 Javascript
Node.JS循环删除非空文件夹及子目录下的所有文件
2018/03/12 Javascript
微信小程序实现带缩略图轮播效果
2018/11/04 Javascript
浅谈Vue数据响应思路之数组
2018/11/06 Javascript
[01:33]一分钟玩转DOTA2第三弹:DOTA2&DotA快捷操作大对比
2014/06/04 DOTA
python ElementTree 基本读操作示例
2009/04/09 Python
Python中线程的MQ消息队列实现以及消息队列的优点解析
2016/06/29 Python
Python基于回溯法子集树模板解决旅行商问题(TSP)实例
2017/09/05 Python
Python输入二维数组方法
2018/04/13 Python
pandas的连接函数concat()函数的具体使用方法
2019/07/09 Python
Python内置函数locals和globals对比
2020/04/28 Python
使用Python-OpenCV消除图像中孤立的小区域操作
2020/07/05 Python
Rockport乐步美国官网:风靡美国的白宫鞋
2016/11/24 全球购物
美国最大的网络男装服装品牌:Bonobos
2017/05/25 全球购物
宏碁西班牙官网:Acer西班牙
2021/01/08 全球购物
大学学生会竞选演讲稿
2014/04/25 职场文书
班主任经验交流材料
2014/12/16 职场文书
离婚协议书范文2015
2015/01/26 职场文书
幼师中班个人总结
2015/02/12 职场文书
小学语文教学反思范文
2016/03/03 职场文书
MySQL表类型 存储引擎 的选择
2021/11/11 MySQL