106

用vue做一个酷炫的menu - MingSeng-W

 6 years ago
source link: https://my.oschina.net/u/3727086/blog/1573075
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

用vue做一个酷炫的menu - MingSeng-W的个人空间 - OSCHINA - 中文开源技术交流社区

        最近看到一个非常酷炫的 menu 插件,一直想把它鼓捣成 vue 形式,谁让我是 vue 的死灰粉呢,如果这都不算爱😔。😆开个小玩耍,我们一起来探索黑魔法吧。观看本教程的读者需要具备一定的 vue 和 css3 的知识.

1. 效果演示

2. 使用方法介绍

3. 关键步骤讲解

1. 效果演示

1240

pic_1

1240

1240

pic_3

     在线演示 live demo

2. 使用介绍

        项目地址:github.com/MingSeng-W/vue-bloom-menu,clone 项目到本地

       a. 首先在单文件组件里引入 menu 组件,导入 common 文件夹 stylus 里的 menuConfig.stylus.

       b. 配置相应的参数

            可选参数

            * radius:default 为 100px,item 距离 menu 的 button 的距离。

            *  startAngle:defaut 为 0,item 开始的角度,以时钟 3 点钟方向记为 0,然后顺时针方向为递增方向。

           *  endAngle:default 为 315,最后一个 item 的角度。

           *  itemNum:default 为 8

            *  animationDuration:default 为 0.5s,每个 item 动画的执行时间

            *  itemAnimationDelay:default 为 0.04s, 每个 item 之间 animation 触发的间隔延迟时间

          必选参数

            * iconImgArr

        import 您需要的 icon, 然后生成 iconImgArr(computed 属性绑定),作为 props 传给 menu 组件

           menu 的位置

    目前有 center,corner 两种位置,在 menu 的 class 里指定。center 的 class:.menu-center-wrapper

corner 的 class:.menu-left-corner-wrapper。当然自己指定位置也是 ok 的。

          一个简单的 example

1240

3. 关键步骤讲解

    整个 menu 的实现关键在于计算 menu 展开后最后的坐标,以及展开与收缩的动画.(由于整个项目布局比较简单,所以这里主要讲解逻辑和动画的实现)

    第一步:计算 menu 展开后横坐标和纵坐标

        下面的 x,y 分别表示 item 在页面的位置,以 x 为例。

    x:原始的位置,x2 最后展开的位置,x1 中间的过渡位置 (主要是造成一个 “拉回” 的效果),以下是图片解释,为了解释简单明了,我放大了 radius 倍数以及增加了动画的执行时间。

1240

    位置的计算:首先计算每个 item 之间的夹角,起始 item 是沿着顺时针布局的,每个 item 之间的夹角等于 (endAngle-startAngle)/(itemNum-1)。当前 item 应该旋转的角度为:angleCur=startAngle+index * 每个 item 之间的夹角。得到 item 的旋转角度之后,用 Math.cos 和 Math.sin 和 radius 相乘得到其横坐标和纵坐标.

    关键代码:

1240

计算每个 item 的夹角

1240

第二步,根据生成的坐标使用 js 动态生成 animtion, 并插入到样式文件中。

1240

生成展开和收缩的 keyframe

到这一步我们完成了点击 menu 展开与收缩。

    第二步,完成点击 item 之后 item 放大与消失,其他的 item 缩小与消失

    item 消失的 keyframe

1240

    item 消失的 keyframe

    这里触发动画使用 vue 提供 transition ,当元素的 v-show 为 false 时,也就是 display 为 none 时,触发动画。

    每个 item 动画完成后都会触发 animationEnd 事件,监听 item 的 animationEnd 事件,当所有动画依次触发完毕之后,提醒 menu 置于关闭状态(父子组件通信 )。

    我在 menu 组件里使用 v-on 监听 animationEnd 事件,item 自己的动画执行后,通过 $emit 触发 animationEnd 事件,通知 menu 的动画计数 count++, 当 count 达到总的项目数的时候,menu 进行关闭.

1240

1240

1240

      再次打开 menu 的时候检查与 item 绑定的 showItem 是否为 false, 是的话置为 true。点击时需要拿到被点击 item 的 index, 得到全局的 currentIndex 即被点击的 item 的 index。被点中的使用放大动画,否则使用缩小动画。

1240

pic_6

1240

至此所有步骤讲解完毕


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK