弹弹弹,弹走鱼尾纹的弹出菜单(vue)
前言
上一篇面试的总结,大家看的还行,因为量很大,错误在所难免,希望大家发现错误了可以告诉我一声,我的邮箱是236490794@qq.com,一个小前端的希望。
言归正传
我们老样子直接先上效果图再开始今天的分享
这个项目的github可以看一看
组件分析
- 界面组成
- 逻辑分析
- 最终实现
界面组成
从上图中,我们可以看出界面主要分为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)的更多相关文章
- Web标准:四、纵向导航菜单及二级弹出菜单
Web标准:四.纵向导航菜单及二级弹出菜单 知识点: 1.纵向列表 2.标签的默认样式 3.css派生选择器 4.css选择器的分组 5.纵向二级列表 6.相对定位和绝对定位 1)纵向列表 可以看 ...
- dragView 屏幕拖拽并且弹出菜单的控件
dragView 因项目新需求需要添加一个屏幕拖拽按钮可以弹出菜单的控件,因为不是我做的闲来无事写一个demo吧 可能存在一些小bug(毕竟就写了几个小时)兄弟姐妹们理解思路就行 具体的可以自己调试一 ...
- 向上弹出菜单jQuery插件
插件名:柯乐义英文名:Keleyijs文件名称:jquery.keleyi.js插件功能:该插件可以让你轻易地在页面上构建一个向上弹出的二级菜单. 示例查看:http://keleyi.com/kel ...
- html5手机端遮罩弹出菜单代码
效果体验:http://hovertree.com/texiao/html5/17/ 效果图: 代码如下: <!doctype html> <html lang="zh&q ...
- DIV+CSS制作二级横向弹出菜单,略简单
没有使用JavaScript控制二级菜单的显示,结果如上图所示. 代码如下: <!DOCTYPE html> <html> <head> <meta char ...
- vc++ 如何添加右键弹出菜单
一.创建新工程 二.编辑菜单资源 1.添加菜单 按"Ctrl+R",双击"Menu"图标 2.于菜单编辑器内编辑菜单 四.添加代码(红色部分) void CCM ...
- 创建 iPhone/iOS8 弹出菜单(窗口)
基本步骤 添加视图:主视图与弹出视图 关联视图 配置弹出视图 编码实现:弹出菜单样式及控制器委托 override func prepareForSegue(segue: UIStoryboardSe ...
- android 单选、多选弹出菜单
菜单单选窗口: import android.app.Activity;import android.app.AlertDialog;import android.content.DialogInte ...
- [Flex] PopUpButton系列 —— 弹出菜单的行高设置
<?xml version="1.0" encoding="utf-8"?> <!--Flex中如何通过variableRowHeight样式 ...
随机推荐
- web开发(六) EL表达式
在网上看见一篇不错的文章,写的详细. 以下内容引用那篇博文.转载于<http://www.cnblogs.com/whgk/p/6432044.html>,在此仅供学习参考之用. 一.EL ...
- PyQt GUI--信号与槽
目录 目录 前言 系统软件 GUI的主循环 信号与槽 信号的应用 使用控件类的内建信号 自定义信号 带参数的信号 槽的应用 创建槽 信号和槽的连接 最后 前言 PyQt中的信号和槽,就是一个触发和执行 ...
- Pycharm断点调试入门
断点调试是在开发过程中常用的功能,能清楚看到代码运行的过程,有利于代码问题跟踪.对我这个小白开发来说,还有一个作用是快速熟悉代码,拿到别人写的代码,有时看不太懂或看的很吃力,光这样看很无感,但是通过断 ...
- 简单方法让input date支持placeholder(包含ios手机端方法)
<input class="baixin-quan-info-box-time" type="text" onfocus="(this.type ...
- squid 3.5.2配置文件
https://www.cnblogs.com/mchina/p/3812190.html 配置文件就加入下面这几句话: cache_mem 64 MB maximum_object_size 4 M ...
- 手写朴素贝叶斯(naive_bayes)分类算法
朴素贝叶斯假设各属性间相互独立,直接从已有样本中计算各种概率,以贝叶斯方程推导出预测样本的分类. 为了处理预测时样本的(类别,属性值)对未在训练样本出现,从而导致概率为0的情况,使用拉普拉斯修正(假设 ...
- 数组转字符串,字符串转数组 join(), split();
join() join() 方法用于把数组中的所有元素放入一个字符串. 元素是通过指定的分隔符进行分隔的. arrayObject.join(separator), 默认为使用逗号分隔 var ar ...
- Oozie 3.3.1安装
软件安装路径 软件名称 版本 安装路径 jdk 1.6.0_12 /usr/java/jdk1.6.0_12 maven 3.1.0 /usr/local//apache-maven-3.1.0 Oo ...
- pycharm中ctrl + C复制, ctrl+A全选等快捷键失效
原因是:在安装pycharm的时候也同时安装了vim插件,需要在settings - > vim Emulation里将相关的handler改成 IDE
- MD5算法+盐Salt
1.MD算法的基的概念 MD5算法是典型的消息摘要算法,其前身有MD2.MD3和MD4算法,它由MD4.MD3和MD2算法改进而来.不论是哪一种MD算法,它们都需 要获得一个随机长度的信息并产生 ...