Bounce, bounce всплывающее меню гусиных лапок (vue)

внешний интерфейс GitHub Vue.js опрос

предисловие

Краткое содержание последнего интервью, его может прочитать каждый, так как объем очень большой, а ошибки неизбежны. Надеюсь, вы мне подскажете, если обнаружите какие-либо ошибки. надеяться.

Ближе к дому

Как обычно, мы загрузим визуализацию непосредственно перед тем, как начать сегодняшнюю публикацию.Гитхаб этого проекта можете глянуть

Компонентный анализ

  1. состав интерфейса
  2. логический анализ
  3. наконец понял
состав интерфейса

Из приведенного выше рисунка видно, что интерфейс в основном разделен на блоки меню и элемента 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

Хорошо, это все, что нужно для обмена.

Мой гитхаб, попроси штамп, попроси звезду