Версия компонента NetEase Music Edition Carousel-React

Архитектура внешний интерфейс React.js
Версия компонента NetEase Music Edition Carousel-React

проиллюстрировать:

Эта версия карусели создана по образцу карусели на домашней странице проигрывателя NetEase Cloud Music для ПК.

Особенность карусели NetEase заключается в том, что если вы сдвинете два изображения, которые не находятся рядом друг с другом, эффект перехода будет не скользящим, а выпрыгивающим.

Эта карусель написана на es6 в среде чистого реагирования, она соответствует стилю за счет реорганизации и упорядочивания массивов в состоянии. добиться эффекта вращения

Без каких-либо зависимостей конечным результатом является инкапсуляция открытого интерфейса компонента реакции и его публикация.

Примечание. Эта статья является предварительным предложением и будет обобщена и оптимизирована после завершения разработки.

1. Построение структуры

Об этом должно быть много статей, поэтому мне не нужно слишком много вводить, просто зайдите на github, чтобы найти фреймворк для создания базовой структуры проекта.

Я использовал фреймворк для улучшения по сравнению с предыдущей версией dva framework.реагировать строительные леса, на гитхабе их много.Рекомендуется выбрать один для улучшения.Тот, что использую я, может вам не подойти.

2. Подготовить материалы

1. Более 4-х картинок одного размера. (я назвал восемь картинок 1-8)
2. Реагировать на среду
3. Облачный проигрыватель NetEase для ПК

3. Развитие

Сначала поместите первую картинку и картинки, которые видны слева и справа. Исходная статическая структура выглядит так
Примечание для новичков: если вы обнаружите, что код ослепителен, синтаксис less и es6 компенсирует это самостоятельно.

import React from 'react';

import styles from './Slide.less';

class Slide extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      dir: [
        { name: 'middle' },
        { name: 'start' },
        { name: 'normal' },
        { name: 'normal' },
        { name: 'normal' },
        { name: 'normal' },
        { name: 'normal' },
        { name: 'end' },
      ],
    };
  }
  render() {
    const { dir } = this.state;
    return (
      <div key={key} className={styles.root}>
        {/* 外部容器*/}
        <div className={styles.slideBox}>
          {/* 内部循环*/}
          {
            dir.map((item, key) => {
              return (
                <div className={`${styles.slide} ${styles[item.name]}`}> // 此处偷懒
                  <img src={`./images/${key + 1}.png`} // 此处偷懒 alt="./images/404.png" />
                  <div // 蒙板
                    className={styles.masking}
                  >{''}</div>
                </div>
              );
            })
          }
        </div>
      </div>
    );
  }
}

export default Slide;


меньше выглядит следующим образом

.root{
  width: 100%;
  background: #ccc;
  .slideBox{
    width: 50%;
    height: 15vw;
    margin: 0 auto;
    position: relative;
    background: #ccc;
    .slide{
      position: absolute;
      img{
        width: 100%;
      }
      .masking{ // 蒙板,有个灰度渐变的效果
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, .15);
      }
      &.middle{ // 此为中间展示的那张
        left: 10%;
        bottom: 0%;
        width: 80%;
        z-index: 33;
      }
      &.start{ // 第一张则为左侧那张
        left: 0%;
        bottom: 0%;
        width: 75%;
        z-index: 22;
        }
      &.end{ // 最后一张及右侧那张
        right: 0%;
        bottom: 0%;
        width: 75%;
        z-index: 22;
      }
      &.normal{ // 此为隐藏图片的样式
        left: 13%;
        bottom: 0%;
        width: 74%;
        z-index: 11;
      }
    }
  }
}

Так задается начальное положение.Расположение скрытой картинки очень важно, потому что, как было сказано выше, при скольжении по картинкам его нужно изменить на всплывающий эффект. Вероятно, в следующем положении показанная картинка отлично его перекрывает.

Далее добавляем события. Давайте проигнорируем ряд точек навигации под каруселью. Сначала добавьте операцию левого и правого щелчка.

Добавьте операцию onClick к слою маски (ее также можно добавить к слою слайда) следующим образом:

<div
    className={item.name === 'middle' ? '' : styles.masking}
    onClick={() => this.slide(item.name, key)}
>{''}</div>

Нажмите на картинку

slide(name, key) {  // 图片点击逻辑
    // 记录当前节点
    this.setState({ current: key });
    // 数组操作方法
    this.imgArr(name);
  }

Метод работы с массивом

imgArr(name) { // 数组处理
    let dirCopy = this.state.dir;
    if (name === 'start') {  // 点击左侧那张
      const pop = dirCopy.pop(); // 从数组尾部弹出一个元素
      dirCopy.unshift(pop); // 尾部元素添加到数组头部
    } else if (name === 'end') { // 点击右侧那张
      const shift = dirCopy.shift(); // 从数组头部弹出一个元素
      dirCopy.push(shift);  // 添加到数组尾部
    }
    this.setState({ dir: dirCopy }); // 保存重新排列的数组 并触发render
}

Добавлен стиль перехода

1. Стиль перехода в основном включает градиент слоя маски при вращении.
2. Плавный переход позиционирования при вращении.
3. Изменение уровня при вращении поясняется отдельно в ссылке на оптимизацию.

.slide{
    ... , // 此处为原样式保留的意思(下面都以此规则显示)
    transition: all 0.3s ease-in-out;
    user-select: none; // 禁止用户选中(防止图片被选中时变色);
    &:hover{ // 鼠标经过时显示小手样式
      cursor: pointer;
    }
}
.masking{
    ... ,
    transition: all 0.3s 0.2s linear;
}
&.middle{
    ... ,
    .masking{
      background: transparent;
    }
}

Таким образом, когда вы нажимаете на левую и правую стороны изображения, вы можете изначально вращать его.

Пройденные шаги в стиле карусели — это самая простая «версия карусели es6», нуждающийся друг уже может быть оптимизирован в приведенном выше коде в своих собственных проектах.

разработка кнопки меню
Динамически переключайте количество кнопок меню в соответствии с количеством изображений, код аналогичен циклу изображения.

<div className={styles.slideBox}>
  ... ,
  {/* 导航按钮*/}
  <div className={styles.point}>
    {
      this.state.dir.map((item, key) => { // 根据图片数量进行循环
        return (
          <span
            key={key}
            className={item.name === 'start' ? styles.hover : ''} // 给予当前显示的按钮样式变化
            onMouseEnter={() => this.pointFunc(key - 1)} // 鼠标进入动画
          >{}</span>
        );
      })
    }
  </div>
</div>

С точки зрения стиля:

  .point{
    width: 100%;
    position: absolute;
    left: 0;
    bottom: -23px;
    z-index: 999;
    text-align: center;
    span{
      display: inline-block;
      width: 20px;
      height: 3px;
      background-color: #2E3033;
      margin-left: 9px;
      &.hover{
        background-color: #7F8082;
      }
      &:hover{
        cursor: pointer;
      }
    }
  }

Мышь входит в метод pointFunc();

  pointFunc(index) { // 按钮点击
    const { current } = this.state;
    const dirCopy = this.state.dir;
    if (index < current) { // 鼠标经过左侧的按钮
      for (let i = 0; i < (current - index); i += 1) { // 判断距离
        const shift = dirCopy.shift(); // 进行数组操作
        dirCopy.push(shift);
      }
    } else if (index > current) { // 鼠标经过右侧的按钮
      for (let i = 0; i < (index - current); i += 1) {
        const pop = dirCopy.pop();
        dirCopy.unshift(pop);
      }
    }
    this.setState({ dir: dirCopy }); // 触发react-render重新渲染页面
    this.setState({ current: index }); // 记录当前图片节点
  }

После добавления изображения кнопки эффект выглядит следующим образом:

В это время основной эффект выступил. После строгой регулировки макета и анимации он, наконец, достигла ожидаемого специального анимационного эффекта игрока NetEaseSease. (Следы мыши, когда он проходит через соседнюю картинку, и он изменяется на эффект прыжки, когда он передает кнопку не прилегающей картинки).

Производительность тегов

注:样式方面还有需要优化的地方请自行调节


Суммировать

在这个组件模式开发时代,如果你做的东西不能保留下来并且开放出去,我认为是一件可悲的事情。所以下一篇文章将把此react组件进行开放式处理,开放一些可调节接口、响应式处理,并且最后打包成npm包,以插件的形式开放出去。