摘要:前言上一篇面試的總結(jié),大家看的還行,因?yàn)榱亢艽?,錯(cuò)誤在所難免,希望大家發(fā)現(xiàn)錯(cuò)誤了可以告訴我一聲,我的郵箱是,一個(gè)小前端的希望。
前言
上一篇面試的總結(jié),大家看的還行,因?yàn)榱亢艽螅e(cuò)誤在所難免,希望大家發(fā)現(xiàn)錯(cuò)誤了可以告訴我一聲,我的郵箱是[email protected],一個(gè)小前端的希望。
我們老樣子直接先上效果圖再開(kāi)始今天的分享
這個(gè)項(xiàng)目的github可以看一看
界面組成
邏輯分析
最終實(shí)現(xiàn)
從上圖中,我們可以看出界面主要分為menu和item2塊,其中menu的動(dòng)畫(huà)是自傳,item的動(dòng)畫(huà)是位移,然后這里我們通過(guò)絕對(duì)布局的方式將整個(gè)控件定位在四個(gè)角落
.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; }
這里我將這個(gè)控件幾個(gè)屬性獨(dú)立出來(lái),方便下次開(kāi)發(fā),其中包含,menu的背景,整個(gè)控件在屏幕的哪個(gè)角落,menu的寬高,item距離menu位移的距離,menu的背景色,及item的背景色,item的相關(guān)內(nèi)容則由數(shù)據(jù)來(lái)控制,具體的我們直接在下方的實(shí)現(xiàn)里來(lái)講解。
這里我用代碼加注釋的方式,幫助大家理解,template我簡(jiǎn)單的帶過(guò)一下
核心實(shí)現(xiàn)
通過(guò)分析可以得出,每個(gè)item的偏移量應(yīng)該為
橫向x:基礎(chǔ)值 * sin(角度值)
縱向y:基礎(chǔ)值 * cos(角度值)
角度值:(數(shù)組的長(zhǎng)度-1-當(dāng)前的下標(biāo)) 每一塊所占的角度 弧度表示
弧度表示:2 * Math.PI / 360
export default { ... props: {//開(kāi)放的屬性,方便自定義 menuSrc: { default: require("../assets/menu.png") }, position: { default: "LT"http://可選擇LT、LB、RT、RB4個(gè)角落 }, width: { default: 50, }, baseDistance: { default: 150, }, menuBg: { default: "white" }, itemBg: { default: "white" }, menuItems: { type: Array, } }, data() { return { openFlag: false,//展開(kāi)合并標(biāo)志 operators: ["+", "+"],//用于記錄展開(kāi)時(shí)動(dòng)畫(huà)XY方向 } }, mounted() { //根據(jù)props初始化各內(nèi)容的各種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; }); //根據(jù)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) {//合并時(shí),點(diǎn)擊展開(kāi)操作 this.menuItems.forEach((item, index) => { this.toggleMenuTransition(item.name, index, false) }); //menu本身轉(zhuǎn)一周 this.$refs.menuHome.style.transform = "rotate(360deg)"; } else { this.menuItems.forEach((item, index) => { this.toggleMenuTransition(item.name, index, true) }); //menu恢復(fù) 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);//橫坐標(biāo)所偏移的比例 let axisY = Math.cos((this.menuItems.length - 1 - index) * oneArea * 2 * Math.PI / 360);//縱坐標(biāo)所便宜的比例 let el = document.getElementById(name);//若所傳的name一直,會(huì)報(bào)錯(cuò)。 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)`;//進(jìn)行動(dòng)畫(huà) }, index * 100)//通過(guò)定時(shí)器的方式,達(dá)到一個(gè)一個(gè)彈出來(lái)的效果 } else { //item恢復(fù) el.style.transitionDuration = "200ms"; el.style.transform = `translate(0,0)`; } }, clickMenu(item, index) { //暴露方法給父組件,進(jìn)行點(diǎn)擊事件的操作 this.$emit("clickMenu", item, index) } } }
再父組件中引入就可以大功告成啦,先跳一會(huì)兒吧,燃燒你的卡路里
引入組件
import toggleMenu from "./toggleMenu"
在 components聲明
components: { toggleMenu },
template中使用
menuItems: [//name和src必填,且name唯一否則會(huì)報(bào)錯(cuò) {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")}, ]屬性及方法一欄
屬性名 | 用處 | 默認(rèn)值 | 是否必須 |
---|---|---|---|
position | 四個(gè)方位(LT、LB、RT、RB) | LT | 否 |
menuBg | 菜單背景 | white | 否 |
menuSrc | 菜單圖片 | 一個(gè)菜單圖片 | 否 |
itemBg | 按鈕背景 | white | 否 |
width | 按鈕寬度 | 50px | 否 |
baseDistance | 位移距離,若item很多,可適當(dāng)提高 | 150px | 否 |
menuItems | 菜單數(shù)組 | 無(wú) | 是 |
方法名 | 用處 | 參數(shù) |
---|---|---|
clickMenu | 點(diǎn)擊item觸發(fā)事件 | item,index |
我的github,求戳,求star
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/54646.html
摘要:前言上一篇面試的總結(jié),大家看的還行,因?yàn)榱亢艽?,錯(cuò)誤在所難免,希望大家發(fā)現(xiàn)錯(cuò)誤了可以告訴我一聲,我的郵箱是,一個(gè)小前端的希望。 前言 上一篇面試的總結(jié),大家看的還行,因?yàn)榱亢艽?,錯(cuò)誤在所難免,希望大家發(fā)現(xiàn)錯(cuò)誤了可以告訴我一聲,我的郵箱是[email protected],一個(gè)小前端的希望。showImg(https://segmentfault.com/img/remote/146000...
摘要:用了,這類(lèi)的框架之后,發(fā)現(xiàn)組件化的開(kāi)發(fā)在大部分時(shí)間很方便,但是有些時(shí)候卻用起來(lái)很變扭。更新今天發(fā)現(xiàn)一個(gè)大失誤,原來(lái)我一直沒(méi)把包發(fā)布到。。。趕緊發(fā)布了一下,如果有任務(wù)問(wèn)題,都可以在的里面提出來(lái) 用了vue,react這類(lèi)的框架之后,發(fā)現(xiàn)組件化的開(kāi)發(fā)在大部分時(shí)間很方便,但是有些時(shí)候卻用起來(lái)很變扭。 比如我需要自定義一個(gè)alert組件,組件寫(xiě)起來(lái)很方便,但是使用的時(shí)候卻是這樣的: ...
摘要:哥決定把小弟的成果納入,不只是看上去很美系列,以示鼓勵(lì)其實(shí)還挺有壓力的,后浪推前浪,新人趕舊人。連續(xù)單擊同一站點(diǎn)連續(xù)單擊同一站點(diǎn)注意不是雙擊,可以將經(jīng)過(guò)此站點(diǎn)的所有線路突出顯示出來(lái)。 前言 最近特別忙,承蒙大伙關(guān)照,3D機(jī)房的項(xiàng)目一個(gè)接著一個(gè),領(lǐng)了一幫小弟,搞搞傳幫帶,烏飛兔走,轉(zhuǎn)眼已經(jīng)菊黃蟹肥……有個(gè)小弟很不錯(cuò),勤奮好學(xué),很快就把API都摸透了,國(guó)慶幾天自己折騰著做了個(gè)HTML5的魔...
閱讀 1373·2019-08-30 15:44
閱讀 2116·2019-08-30 11:04
閱讀 535·2019-08-29 15:17
閱讀 2556·2019-08-26 12:12
閱讀 3146·2019-08-23 18:09
閱讀 932·2019-08-23 15:37
閱讀 1533·2019-08-23 14:43
閱讀 2940·2019-08-23 13:13