上一篇面試的總結,你們看的還行,由於量很大,錯誤在所不免,但願你們發現錯誤了能夠告訴我一聲,個人郵箱是236490794@qq.com,一個小前端的但願。javascript
咱們老樣子直接先上效果圖再開始今天的分享css
這個項目的github能夠看一看html
從上圖中,咱們能夠看出界面主要分爲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的相關內容則由數據來控制,具體的咱們直接在下方的實現裏來說解。 vue
這裏我用代碼加註釋的方式,幫助你們理解,template我簡單的帶過一下java
<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 / 360git
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) } } }
再父組件中引入就能夠大功告成啦,先跳一下子吧,燃燒你的卡路里 github
引入組件面試
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 |