博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
弹弹弹,弹走鱼尾纹的弹出菜单(vue)
阅读量:7201 次
发布时间:2019-06-29

本文共 4771 字,大约阅读时间需要 15 分钟。

hot3.png

前言

言归正传

我们老样子直接先上效果图再开始今天的分享

组件分析

  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我简单的带过一下

核心实现 通过分析可以得出,每个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')},]

属性及方法一栏

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

好了,差不多就分享这么多,

转载于:https://my.oschina.net/u/3964441/blog/2049539

你可能感兴趣的文章
java web 分页实现
查看>>
谈谈区块链的理解 -- 读《区块链:技术驱动金融》
查看>>
模板类声明和定义 (转)
查看>>
RSync 远程同步工具的使用
查看>>
C++访问mysql数据库
查看>>
字符测试与映射函数 ctype.h
查看>>
关于Spring的69个面试问答——终极列表
查看>>
MyBatis參数格式化异常解决方式:MyBatisSystemException:
查看>>
核心动画中的动画组和转场动画
查看>>
git 命令自动补全
查看>>
(转)真实经纬度的最简单获得方法
查看>>
解读微信公众号的推广运营之道
查看>>
以后不用再出门购物?下单菜鸟就从你家门口发货,2小时就能到!
查看>>
我知道苏宁会玩,但没想到它能把“千人千面”玩到了极致
查看>>
年终回顾:2017年的重大软件开发事态发展
查看>>
国家邮政局:去年12月快递服务申诉量同比下降25.9%
查看>>
山西藏家捐献44幅明清寺观壁画在山西博物院展出(图)
查看>>
日本统合幕僚长否认“威胁飞行” 要求韩方冷静应对
查看>>
美银行电讯业出手援助联邦雇员 政府重开见曙光?
查看>>
去年检察机关依法决定不批捕29万余人 同比上升10.8%
查看>>