предисловие
Краткое содержание последнего интервью, его может прочитать каждый, так как объем очень большой, а ошибки неизбежны. Надеюсь, вы мне подскажете, если обнаружите какие-либо ошибки. надеяться.
Ближе к дому
Как обычно, мы загрузим визуализацию непосредственно перед тем, как начать сегодняшнюю публикацию.Гитхаб этого проекта можете глянуть
Компонентный анализ
- состав интерфейса
- логический анализ
- наконец понял
состав интерфейса
Из приведенного выше рисунка видно, что интерфейс в основном разделен на блоки меню и элемента 2. Анимация меню — автобиография, а анимация элемента — смещение, Затем мы располагаем весь элемент управления в четырех углах по абсолютной компоновке.
.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;
}
логический анализ
Здесь я разделяю несколько свойств этого элемента управления для удобства последующей разработки, в том числе фон меню, в каком углу экрана находится весь элемент управления, ширину и высоту меню, расстояние между пунктом и меню, цвет фона меню и элемента. Цвет фона элемента управляется данными, и мы объясним это непосредственно в реализации ниже.
наконец понял
Здесь я использую способ добавления комментариев к коду, чтобы вам было понятно, я просто взял шаблон
<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>
Основная реализация Его можно получить путем анализа, и смещение каждого элемента должно быть Пейзаж 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: {
toggleMenu
},
используется в шаблоне
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 | Расстояние смещения, если предметов много, его можно соответствующим образом увеличить | 150px | нет |
menuItems | массив меню | без | да |
имя метода | полезность | параметр |
---|---|---|
clickMenu | Щелчок по элементу запускает событие | item,index |