弹弹弹,弹走鱼尾纹的弹出菜单(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样式 ...
随机推荐
- iOS 图表工具charts之LineChartView
关于charts的系列视图介绍传送门: iOS 图表工具charts介绍 iOS 图表工具charts之LineChartView iOS 图表工具charts之BarChartView iOS 图表 ...
- 关于 if __name__ == '__main__':的使用
当是用 if __name__ == '__main__': 时,下面调用函数只是在当前脚本调试, 而我们需要在别处导入这个脚本中的类或者函数时,这个if __name__ == '__main__ ...
- Linux从一个服务器拷贝文件到另一个服务器上
***复制文件夹到另外一个服务器scp -r tmp root@114.215.80.12:/work/temp输入密码 scp -r customer root@114.215.80.12:/hom ...
- asp.net mvc中用 log4net记录日志到数据库中
1.log4net官网配置相关,创建数据库 http://logging.apache.org/log4net/release/config-examples.html CREATE TABLE [d ...
- java:(监听,上传,下载)
1.监听: index.jsp: <%@ page language="java" import="java.util.*" pageEncoding=& ...
- Java程序设计——反转字符串 & 找朋友 & 计算int型二进制1的个数 & 情报加密 & 计算日期 & 求近似数 & 输出较小数(练习1)
作为刚刚入门Java的选手,其实C++的功底起到了很大的作用.但是,Java之于C++最大的不同,我个人认为,是其类的多样性.才入门的我,写着老师布置的简单的面对过程的题,如果是C++,可以算是简单了 ...
- redis学习(三)
如何保障reids的数据安全和性能? 一.持久化选项 1.快照snapshotting 它可以将存在于某一时刻的所有数据都写入硬盘里面. 配置选项示例: save 60 1000 注:从最近一次创 ...
- python 并发编程 socket 服务端 客户端 阻塞io行为
阻塞io行为 server.accept server.recv client.send recv,accept 分为两个阶段 1.wait for data 对方把数据经过网络延迟送到自己的操作系 ...
- CDH的ntp时间同步
云服务器: ntpq -p ntpdate -u 10.52.255.1 #手动同步 自建NTP服务器: https://www.cnblogs.com/yinzhengjie/p/9480665. ...
- 开发维护中遇到问题---eclipse、发版问题
1.jar包冲突问题, [服务器启动service服务器,tomcat也已启动]然后浏览器访问,会出现这样子的问题现象:tomcat什么的启动成功,但是访问时会出现404: 解决方法:先停掉tomca ...