preface
The summary of the last interview, we look at the line, because the amount is very large, mistakes are inevitable, I hope you can tell me if you find mistakes, my email is [email protected], a small front-end hope.
Get to the point
As usual, we’ll go straight to the renderings and then start today’s sharing of the project on Github
Component analysis
- An interface
- Logical analysis
- Finally realize
An interface
From the figure above, we can see that the interface is mainly divided into Menu and Item2. The animation of Menu is autobiography, and the animation of Item is displacement. Then, we position the whole control in four corners through absolute layout
.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;
}
Copy the code
Logical analysis
Here, I will separate several properties of this control for the convenience of next development, including the background of menu, which corner of the whole control on the screen, the width and height of menu, the distance between item and Menu displacement, the background color of Menu, and the background color of item. The related content of item is controlled by data. The details will be explained directly in the implementation below.
Finally realize
I’m going to use code and comments here to help you understand, and TEMPLATE is just a little bit of an introduction
<div>
<div class="menu_container" ref="menuHome" @click="toggleMenu">
<img :src="menuSrc"><! - menu figure -- -- >
</div>
<div class="menu_item" v-for="(item,index) in menuItems" :id="item.name" @click="clickMenu(item,index)">
<img :src="item.src"><! - item figure -- -- >
</div>
</div>
Copy the code
Through analysis of the core implementation, it can be concluded that the offset of each item should be horizontal X: base value * sin(Angle value) Vertical Y: base value * cos(Angle value) Angle value: (length of array -1- current subscript) * Angle occupied by each piece * radian indicates that radian indicates: 2 * Math.PI / 360
export default{... props: {// Open attributes for easy customization
menuSrc: {
default: require('.. /assets/menu.png')},position: {
default: 'LT'// Select LT, LB, RT, RB4 corners
},
width: {
default: 50,},baseDistance: {
default: 150,},menuBg: {
default: 'white'
},
itemBg: {
default: 'white'
},
menuItems: {
type: Array,
}
},
data() {
return {
openFlag: false.// Expand the merge flag
operators: ['+'.'+'].// record the XY direction of the animation as it unfolds
}
},
mounted() {
// Initialize various styles for each content according to props
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 = `The ${this.width * 0.8}px`;
el.style.height = `The ${this.width * 0.8}px`;
el.style.lineHeight = `The ${this.width * 0.8}px`;
el.style.background = this.itemBg;
});
// Select different positions according to 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) {// To merge, click expand
this.menuItems.forEach((item, index) = > {
this.toggleMenuTransition(item.name, index, false)});// Menu itself rotates once
this.$refs.menuHome.style.transform = 'rotate(360deg)';
} else {
this.menuItems.forEach((item, index) = > {
this.toggleMenuTransition(item.name, index, true)});/ / the menu
this.$refs.menuHome.style.transform = 'rotate(0)';
}
this.openFlag = !this.openFlag;
},
toggleMenuTransition(name, index, revert) {
let oneArea = 90 / (this.menuItems.length - 1);// The Angle occupied by each piece
let axisX = Math.sin((this.menuItems.length - 1 - index) * oneArea * 2 * Math.PI / 360);// The scale offset by the abscissa
let axisY = Math.cos((this.menuItems.length - 1 - index) * oneArea * 2 * Math.PI / 360);// The ratio of cheapness on the y-coordinate
let el = document.getElementById(name);// If the name is always passed, an error will be reported.
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)`;// Animate
}, index * 100)// Through the timer mode, to achieve a pop-up effect
} else {
/ / the item back
el.style.transitionDuration = '200ms';
el.style.transform = ` ` translate (0, 0);
}
},
clickMenu(item, index) {
// Expose the method to the parent component for the click event operation
this.$emit('clickMenu', item, index)
}
}
}
Copy the code
Add it to the parent component and you’re done. Dance for a while to burn off your calories
Parent component call
The introduction of the component
import toggleMenu from './toggleMenu'
Copy the code
The components statement
components: {
toggleMenu
},
Copy the code
The template used in
{name: 'menu1', SRC: require('../assets/emoji.png')}, {name: 'menu2', SRC: {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>Copy the code
Properties and methods column
The property name | use | The default value | Whether must |
---|---|---|---|
position | Four directions (LT, LB, RT, RB) | LT | no |
menuBg | Menu background | white | no |
menuSrc | Menu pictures | A menu image | no |
itemBg | Button background | white | no |
width | Width of the button | 50px | no |
baseDistance | Displacement distance, if there are many items, can be appropriately increased | 150px | no |
menuItems | Menu array | There is no | is |
The method name | use | parameter |
---|---|---|
clickMenu | Clicking on item triggers the event | item,index |
Okay, so that’s about it,
My Github, ask stamp, ask star